[チュートリアル5]世界各国の時間を表示するアプリを作る[compose multiplatform]
はじめに
ページの基本要素を作る
composeApp/src/commonMain/kotlinのApp.ktを開いてください。
現在のコードを消して以下のコードを挿入してください。
@Composable
fun App() {
MaterialTheme {
var timeAtLocation by remember { mutableStateOf("No location selected") }
Column {
Text(timeAtLocation)
Button(onClick = {
timeAtLocation = "13:30"
}) {
Text("Show Time At Location")
}
}
}
}
それに伴い以下のimportを挿入してください。
import androidx.compose.foundation.layout.Column
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
簡単な解説
このレイアウトは、2つのコンポーザブルを含むカラム(列)です。最初のコンポーザブルはテキストで、2つ目はボタンです。
2つのコンポーザブルはtimeAtLocationプロパティを共有して持っています。
テキストコンポーザブルはこの状態のオブザーバー(監視者)なので、timeAtLocationプロパティの中身をリアルタイムで表示しています。
ボタンコンポーザブルはonClickハンドラーを使って、クリックされたらtimeAtLocationの中身に"13:30"を入れています。
ユーザーの入力を受け付けるようにする
ここでの目標は、ユーザーが都市名を入力すると、その場所の時刻が表示されるようにすることです。
そのためにユーザーが入力できるフォームをTextFiledコンポーザブルで実装します。
App.ktを以下の内容に書き換えてください。
@Composable
fun App() {
MaterialTheme {
var location by remember { mutableStateOf("Europe/Paris") }
var timeAtLocation by remember { mutableStateOf("No location selected") }
Column {
Text(timeAtLocation)
TextField(value = location, onValueChange = {
location = it
})
Button(onClick = {
timeAtLocation = "Time at $location is 13:30"
}) {
Text("Show Time At Location")
}
}
}
}
importにはこれを追加してください。
import androidx.compose.material.TextField
簡単なコード解説
TextFieldとlocationプロパティを追加しました。
TextFieldは文字の入力フォームで、onValueChangeイベントハンドラーによって、文字が入力されるとその文字をlocationに代入します。
そのlocationをtimeAtLocationで使って、Textの中とかで使っています。
時間を計算する
ユーザーの入力を使って、表示する時間を計算します。そのためにcurrentTimeAt()というファンクションを作りましょう
currentTimeAt()
App.ktに戻って、以下のコードを追加します。
ファイルの一番下で大丈夫です。
fun currentTimeAt(location: String): String? {
fun LocalTime.formatted() = "$hour:$minute:$second"
return try {
val time = Clock.System.now()
val zone = TimeZone.of(location)
val localTime = time.toLocalDateTime(zone).time
"The time in $location is ${localTime.formatted()}"
} catch (ex: IllegalTimeZoneException) {
null
}
}
それに伴って、以下のimport分も追加しましょう。
import kotlinx.datetime.Clock
import kotlinx.datetime.IllegalTimeZoneException
import kotlinx.datetime.LocalTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
currentAtTime()を使ってみる
App()コンポーザブルの中で先ほど作ったcurrentTimeAt()を使うように修正しましょう。
App.ktの29行目あたりに、
timeAtLocation = "Time at $location is 13:30"
こういう記述があると思います。
これを以下のように修正してください。
timeAtLocation = currentTimeAt(location) ?: "Invalid Location"
これによって、元々は固定で13:30を表示していたところに、currentTimeAtファンクションにlocationの値を渡した時の返り値を表示するようになります。
元々のチュートリアルはもうちょっとあるんですが、ちょっと長いのでここまで!
次
残りは次の記事でやります!
Discussion