Using ViewModel in Jetpack Compose
This is a short memo about using ViewModel in Jetpack Compose.
Add Dependencies
- You should use the latest version of the dependencies written in the document below.
- lifecycle-viewmodel-compose
- runtime-livedata
// To use 'viewModel()` in composable implementation "androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07" // To use `observeAsState' in composable implementation("androidx.compose.runtime:runtime-livedata:1.0.0-rc02")
create ViewModel
- I think ViewModel is the same to what it used to be in not Composable.
class MyViewModel(): VIewModel() { private val _name = MutableLiveData("") val name: LiveData<String> = _name }
Observe LiveData in Compose
@Composable fun NameComposable(viewModel: MyViewModel = viewModel()) { val name: String by viewModel.name // use name or change name }
It works!
Androidでタイマーアプリを作る Jetpack Compose
こんにちは。
タイマーアプリとかカウントダウンアプリとか、まぁ呼び方は何でもよいですがフロントの勉強するってなるとおすすめですよね。
ってことで今回はAndroidの新しいUIシステムであるJetpack Composeでタイマーアプリを作るために、CircularProgressIndicator
という便利なコンポーズを見ていきましょう。続きがあるかは謎です。
はい、これだけです。これで50%プログレスが100×100で色は黒、太さは10dpのドーナッツ型のプログレスの出来上がりです。
CircularProgressIndicator( progress = 0.5f, modifier = Modifier .height(100.dp) .width(100.dp), color = Color.Black, strokeWidth = 10.dp )
引数のprogressを下記のようにanimateFloatAsState
で状態として持ってあげればよいですね。
var progress by remember { mutableStateOf(0f) } val animatedProgress by animateFloatAsState( targetValue = progress, animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec )
逆回りにしたいときはanimateProgressを1->0に減らしていけばよいです。
Jetpack ComposeのonSizeChangedとonGloballyPositioned
こんにちは。
今日は Jetpack Compose
の公式サンプルアプリの一つであるJetsurvey
のソースコードでお勉強しています。
そこで onSizeChanged
と onGloballyPositioned
というものが出てきてドキュメントを読み調べてみました。
onSizeChanged
まずこいつですが、名前的にサイズが変更されたときに呼ばれるのかなと思いました。ただ挙動を見ている限りどうも最初も呼ばれている模様。下記のドキュメントに普通に書いていましたが最初のコンポーズ時とサイズが変わった時に呼ばれるみたいです。
[onSizeChanged] wiill only be invoked during the first time measurement or when the size has changed.
またonSizeChanged
を下記のように子要素にも記述した場合、初回コンポーズ時は子要素から呼ばれます。(2 -> 1となる。)
(これは子要素の大きさが決まって初めて親要素の大きさも決まっていく感じですかね?)
Box( modifier = Modifier.onSizeChanged { 1 } ) { Box( modifier = Modifier.onSizeChanged { 2 } ) }
onGloballyPositioned
次はこいつです。 要素の配置が変更されたときに呼ばれます。またドキュメントにもありますが、初回コンポーズ時にもしっかり呼ばれます。
Note that it will be called after a composition when the coordinates are finalized.
下記のような場合は親要素から呼ばれます。(1 -> 2)
Box( modifier = Modifier.onGloballyPositioned { 1 } ) { Box( modifier = Modifier.onGloballyPositioned { 2 } ) }
Jetpack ComposeのRememberとStateについて
こんにちは!今日はRemember
とMutableState
についてのメモです。
mutableStateof
について
mutableStateOf
はComposable内で監視可能な状態変数を作成します。`mutableStateOf()'で作成した変数の値が変わるとその値を読み込むComposableやラムダの再コンポーズが実行されます。remember
について
remember
を使用することで再コンポーズ後もmutableState
で作成した変数を記憶しておくことができます。remember
がないとせっかく再コンポーズを行っても値を保持していないので値が初期化されています。
val name = mutableStateOf("") // name.value = "hoge"などで値を変更するとnameを使用するComposableやラムダの再コンポーズが行われます。しかし実際に再Composeを行うとrememberがないので再度name=""で初期化されてしまいます。
var name = remember { "" } // 反対にrememberだけだといくらnameの値を書き換えても再コンポーズは行われません。なぜならJetpack ComposesはStateオブジェクトが変更されたときのみ再コンポーズが行われるからです。
よって公式にもあるように下記のように書くことになります。
val name = remember { mutableStateOf("") }
参考
Jetpack ComposeのCompositionLocalProviderとは
こんばんは。
Jetpack Composeの公式サンプルアプリの一つであるJetsurveyのソースコードを読んでいてCompositionLoacalProvider
というものが分からなかったため調べてみました。
どうやらCompositionLocalProvider
のラムダ内では引数として渡さなくても事前定義した変数を使いまわせるみたいです。
例を見てましょう。
まず以下のようなデータクラスがあるとします。
data class CompositionData( val name: String = "" )
次に `compositionLocalOf()' で変数のデフォルトを定義します。ラムダ内の処理がデフォルト値となるようです。
val LocalUser = compositionLocalOf {
CompositionData()
}
最後に`CompositionLocalProvider()'を記述します。
CompositionLocalProvider(LocalUser provides CompositionData("gouta", 100)) { MyContent() //変数を使用したいCompose関数 }
'MyContent()'には引数として明示的にデータを渡していませんが以下のように使用することができます。
@Composable fun MyContent() { val user = LocalUser.current Text( text = user.name, modifier = Modifier.fillMaxWidth(), ) }
まとめ
以上、CompositionLocalProvider
の簡単な説明でした。変数がGlobalチックになるので使いまわしは危険そうです。しかし公式の実装にもあるようにContextの取得など他にも便利なものがあるので使ってみたいと思います。
LocalContext
- 'LocalConfiguration'
- 'LocalLifecycleOwner'
などなど
参考
This version (1.0.0-beta06) of the Compose Compiler requires Kotlin version 1.4.32 but you appear to be using Kotlin version 1.4.30 which is not known to be compatible.
こんにちは。
Jetpack Composeを試そうとした際にビルドエラーが出たときの対処です。
This version (1.0.0-beta06) of the Compose Compiler requires Kotlin version 1.4.32 but you appear to be using Kotlin version 1.5.0 which is not known to be compatible.
ComposeのコンパイラはKotlinの1.4.32を使用しなければいけないのに、1.5.0を使っているから駄目だというかんじですね。
あれ、KotlinのVersionってどこで指定するんだっけ?
結論
プロジェクトのbuild.gradle
に下記を追加すればよいです。
buildscript { dependencies { classpath "com.android.tools.build:gradle:7.0.0-alpha15" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.32" // これを追加 } }
感想
Kotlinは結局Gradleのプラグインとしてダウンロードされているのですね。。。これで簡単にKotlinのバージョンを指定できるようになりました。
Navigation ComponentでpopEnterAnimが効かない
今日はAndroidのNavigation Componentについてです。
早速ですがフラグメント間の遷移でアニメーションを付けるためにnavファイルのenterAnim
、exitAnim
、popEnterAnim
、popExitAnim
をいじっていました。
実行してみたところなぜかpopEnterAnim
のみアニメーションが反映されませんでした。
環境は以下です。
def nav_version = "2.3.5" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
とりあえず修正方法
こちらより、以下を試してみたところ治りました。
- gradleに以下の依存関係を使いすることで修正しました。
implementation 'androidx.fragment:fragment-ktx:1.3.3'
理由が分かったら追記する予定です。(なんでfragment-ktxを追加しただけで治ったのだろう?)