Closed4

Modifier修飾子を見る(2)

mtkw0127mtkw0127

Modifier#layoutによるレイアウト修飾子の作成

Modifierの拡張関数としてカスタム修飾子は作成可能。

Modifier#layoutによってレイアウトの要素測定と配置の変更が可能。
Modifier#layoutの戻り値の型はModifierのためチェーンが可能。

以下のように書いてみた。
親の中央に配置するというもの。

fun Modifier.setCenter() = layout { measurable, constraints ->
    return@layout layout(constraints.maxWidth, constraints.maxHeight) {
        val measured = measurable.measure(constraints)
        // 画面の中央を計算
        val centerPosition = Alignment.Center.align(
            size = IntSize(measured.width, measured.height),
            space = IntSize(constraints.maxWidth, constraints.maxHeight),
            layoutDirection
        )
        // 配置
        measured.place(centerPosition)
    }
}

@Composable
fun CustomLayoutModifierTest() {
    Text(
        text = "Hoge",
        Modifier.setCenter(),
    )
}

中心に"Hoge"という文字が来ていた。

mtkw0127mtkw0127

Modifier#composedによる状態を持たせたカスタム修飾子

インターフェースはこんな感じ。Modifierを作るfactoryを渡せばthenで繋いでくれる。
このfactoryがComposableのためrememberを呼ぶことができ状態を保持できる。

fun Modifier.composed(
    inspectorInfo: InspectorInfo.() -> Unit = NoInspectorInfo,
    factory: @Composable Modifier.() -> Modifier
): Modifier = this.then(ComposedModifier(inspectorInfo, factory))

見様見真似で書いてみた。クリックしたら背景色が変わるようにしてみた。
clickableを内部で使っているため呼び出し元でclickableが効かなくなってしまった。

fun Modifier.clickAndChangeBackground(
    callback: () -> Unit,
) = composed {
    var isSelected by remember { mutableStateOf(false) }
    val backgroundColor = if (isSelected) Color.Red else Color.White
    background(backgroundColor)
        .then(
            clickable {
                isSelected = isSelected.not()
                callback.invoke()
            }
        )
}

@Composable
@Preview
fun CustomModifierTest() {
    Text(
        "text",
        modifier = Modifier
            .clickAndChangeBackground {
                println("Hello World")
            }
    )
}
mtkw0127mtkw0127

composedの第一引数inspectorInfo

デバッグするときに使える。

Layout Inspectorに情報を表示できる。以下のように設定してみた。

fun Modifier.clickAndChangeBackground() = composed(
    inspectorInfo = debugInspectorInfo {
        name = "clickAndChangeBackground"
        properties["test"] = "test"
    }
) {
    var isSelected by remember { mutableStateOf(false) }
    val backgroundColor = if (isSelected) Color.Red else Color.White
    background(backgroundColor)
        .then(
            clickable {
                isSelected = isSelected.not()
            }
        )
}

表示されていた。

このスクラップは2023/10/01にクローズされました