【Android】はじめてのJetpack Composeで時計を表示するアプリを作ってみた

# はじめに
今回は、ずっと存在は知っていたが使ったことがなかったJetpack Composeでアプリを作ってみました！
余談ですが、自宅のAndroidStudioの開発環境を最近Flamingoに変えて「Empty Activity」で作成したらJetpack Composeのアプリでできることをちょっと前に知りました。（気付くのが遅いですね。。。）
今はまだxmlでの開発が私は多いのですが、今後を考えるとJetpack Composeでの開発も増えていくのではと言うことで触ってみることにしました。

# アプリ説明
特別なことはしないでただ時間を表示するアプリです。
フォーマットとしては hh : mm : ss を表示しています。
以下が画像です！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117699/002b4937-d720-4a5c-50d7-0a415e57dc94.jpeg" width="300px">

# 実際のコード
次は実際のコードです。今回はFlamingoの「Empty Activity」でプロジェクトを作成してbuild.gradleの修正はしていません！！
```kotlin: MainActivity.kt

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            DisplayTimeAppTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    TimeLayout()
                }
            }
        }
    }
}

private enum class TimeTable(val id: Int) {
    AM(0),
    PM(1)
}

/**
 * １桁だった場合頭に0を追加する
 *
 * @param time 時間
 */
private fun zeroFillFormat(time: String): String {
    return time.padStart(2, '0')
}

/**
 * 24時間表記にする
 *
 * @param am_pm amかpmの数値
 * @param hour 時間(hh)
 */
private fun changeTimeTable(am_pm: Int, hour: Int): String {
    if (TimeTable.PM.id == am_pm) {
        // PMだった場合変換する
        return when (hour) {
            0 -> "12"
            1 -> "13"
            2 -> "14"
            3 -> "15"
            4 -> "16"
            5 -> "17"
            6 -> "18"
            7 -> "19"
            8 -> "20"
            9 -> "21"
            10 -> "22"
            11 -> "23"
            else -> hour.toString()
        }
    }
    return hour.toString()
}

@Composable
fun TimeLayout() {
    val calendar = Calendar.getInstance()
    var hour by remember { mutableStateOf(calendar.get(Calendar.HOUR_OF_DAY).toString()) }
    var min by remember { mutableStateOf(calendar.get(Calendar.MINUTE).toString()) }
    var second by remember { mutableStateOf(calendar.get(Calendar.SECOND).toString()) }
    LaunchedEffect(true) {
        while (true) {
            // 1秒ごとに実行する
            delay(1000)
            val calendar = Calendar.getInstance()
            // 時間(hh)
            hour = zeroFillFormat(
                changeTimeTable(
                    calendar.get(Calendar.AM_PM),
                    calendar.get(Calendar.HOUR_OF_DAY)
                )
            )
            // 時間(mm)
            min = zeroFillFormat(calendar.get(Calendar.MINUTE).toString())
            // 時間(ss)
            second = zeroFillFormat(calendar.get(Calendar.SECOND).toString())
        }
    }
    val density = LocalDensity.current
    // レイアウト
    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.Center
    ) {
        Text(text = hour, fontSize = with(density) { 60.dp.toSp() }, fontWeight = FontWeight.Bold)
        Text(text = " : ", fontSize = with(density) { 60.dp.toSp() }, fontWeight = FontWeight.Bold)
        Text(text = min, fontSize = with(density) { 60.dp.toSp() }, fontWeight = FontWeight.Bold)
        Text(text = " : ", fontSize = with(density) { 60.dp.toSp() }, fontWeight = FontWeight.Bold)
        Text(text = second, fontSize = with(density) { 60.dp.toSp() }, fontWeight = FontWeight.Bold)
    }
}

@Preview(showBackground = true)
@Composable
fun PreviewTimeLayout() {
    // プレビュー表示
    DisplayTimeAppTheme {
        TimeLayout()
    }
}
```

# 苦戦したところ
苦戦したところがありました。
1. テキストを差し替える方法
1. １秒ごと実行する方法

xmlの時は `view.setText`で差し替えできていましたが、今回はxmlとは違いidがあるわけではないのでどうすればいいかわからなかったです。
次に１秒ごとに実行する方法もわかりませんでした。具体的に言うと `１秒ごとに実行　→ そしてレイアウトを差し替える`　この一連の流れのやり方がわからずに少し詰まっていました。

# 最後に
使ってみた感想としては属性はxmlとほぼ同じでしたので大抵は読めばわかるのかなという感じでしたが、今回のレイアウトの構成はすごく単純でしたのであまり時間がかかっていませんが、複雑なレイアウトになればなるほど大変そうだなと感じました。（慣れていないだけかもしれないですが。。）
ただ、Kotlinファイルだけで完結するなんてすごいなと思いました。
でもやはりxmlと違うところがあるので個人的に慣れるまで時間がかかりそうだなと感じました。
もしおかしな実装になっていればご指摘いただけると嬉しいです。
最後までご覧いただきありがとうございました。