Swift, Kotlin などの言語では拡張関数なるものを定義する事が可能で、好きなクラスにメソッドを生やす事が可能です(Int
などの基本的なクラスに対してさえ可能)。
今回はこの機能を使って Jetpack Compose でのカスタム Modifier を作成しました。
[目次]
環境
- compileSdk 33 - kotlinCompilerVersion '1.6' - compose_ui_version = '1.2.1'
拡張関数
拡張関数とは、好きなクラスにメソッドを生やすことが可能な機能です(String, Int などにも可能です)。
今回、機能を詳細に説明することは避けますが、理解に必要なため紹介します。
// Int クラスに `square()` というメソッドを生やす例 fun Int.square(): Int { return this * this } // 呼び出し方 val area = 3.square()
// String クラスに `sayHello()` というメソッドを生やす例 fun String.sayHello(): String { return "hello ${this}" } // 呼び出し方 val text = "world".sayHello()
通常のメソッドのように呼び出せて非常に便利です。
もちろん、Android Studio の補完も効きます。
Modifier とは
Jetpack compose
Jetpack Compose とは、Android における宣言的 UI ツールキットで、従来の XML を置き換えるものです。
最新の安定版 version は 1.2.1(2022/10/18 現在)と比較的新しい技術ですが、すでに多くの国内外の企業で使われており、非常に注目されています。
UI 部分も Kotlin で記述可能なこと、また、Vue, React などのフロントエンドでの宣言的 UI とも考えが似ている部分も導入しやすさにつながっていそうです。
Modifier
Jetpack Compose での Modifier は、HTML における CSS 的な位置付けです。
Modifier メソッドを重ねていくことでスタイルを調整する事が可能です。
(基本は当てた順に適応されていくので、そこは注意が必要です。)
Text( text = "Text!!", modifier = Modifier .fillMaxSize() .background(Color.Red) .clip(CircleShape) .clickable { println(" Clicked!!") } )
カスタム Modifier
各要素に同じスタイルを当てたい時などがあると思いますが、そういう時に自分でメソッドを生やしちゃいます。
Getting Started
Kotlin はトップレベルに関数を宣言する事ができるので、ファイルの好きな部分に以下のように定義します。
(メソッドチェーンで繋げていくためにメソッドの戻り値を Modifier にしてます。)
// 円形に切り取り、背景を赤くする Modifier fun Modifier.redBall(): Modifier = clip(CircleShape) .background(Color.Red) .size(250.dp)
そして、以下のように redBall を呼んであげます。
(もちろん、補完も効きます。)
@Composable fun ModifierTest() { Box( modifier = Modifier .redBall(), ) }
composables にアクセスする
状態を管理する変数など、composition にアクセスする必要がある時は、Modifier.composed を使ってあげます。
以下は、背景を緑色にしながら指定したサイズに切り取り、一定間隔で回転を続ける Modifier の例です。
fun Modifier.greenBoxRotate( size: Dp, duration: Int, ): Modifier = composed { // この情報を使用するのに composable である必要がある。 val transition = rememberInfiniteTransition() val angleRatio by transition.animateFloat( initialValue = 0f, targetValue = 1f, animationSpec = infiniteRepeatable( // tween, keyframes など animation = keyframes { durationMillis = duration }, // Reverse or Restart repeatMode = RepeatMode.Reverse, ), ) size(size) .graphicsLayer( rotationZ = 360f * angleRatio, alpha = 1f * angleRatio, ) .background(Color.Green) }
実際に Modifier を使ってみた例はこちらになります。
@Composable fun ModifierTest() { Box( modifier = Modifier .redBall(), contentAlignment = Alignment.Center, ) { Box( modifier = Modifier .greenBoxRotate( size = 100.dp, duration = 3000, ) ) Box( modifier = Modifier .greenBoxRotate( size = 200.dp, duration = 1200, ) ) } }
謎の動きが完成しました。
おわりに
Kotlin を使える、それだけで Android を書く理由になりそう。