kotlin Android Compose中基于特定条件的链接修饰符

unhi4e5o  于 2023-11-21  发布在  Kotlin
关注(0)|答案(7)|浏览(201)

我想以这样一种方式应用修饰符,即如果提供了宽度,它应该使用提供的宽度,否则使用可用的最大宽度。
我正在应用修改器在下面的时尚,但结果并不像预期的那样。视图宽度是去乱糟糟的。请求指导这里。

val myModifier = Modifier.padding(
    start = 4.dp, end = 4.dp, top = 8.dp, bottom = 8.dp
)

if (viewWidth == null)
    myModifier.then(Modifier.fillParentMaxWidth(1f))
else
    myModifier.then(Modifier.width(viewWidth))

myModifier.then(
    Modifier.height(viewHeight ?: 100.dp)
        .clickable(onClick = { listener.onItemClick(item) })
)

字符串

xpcnnkqh

xpcnnkqh1#

您可以通过扩展函数创建条件修改器:

fun Modifier.conditional(condition : Boolean, modifier : Modifier.() -> Modifier) : Modifier {
    return if (condition) {
        then(modifier(Modifier))
    } else {
        this
    }
}

字符串
这让你可以像这样在conditional块中链接一个修改器:

val applySpecialBackground : Boolean = [...]
Column(
    modifier = Modifier
        .fillMaxWidth()
        .conditional(applySpecialBackground) {
            background(Color.Red)
        }
        .padding(16.dp)

) { [...] }


它只会在条件为true时应用条件修饰符。
如果你需要为false情况添加一个修饰符,只需链接第二个否定条件。

val applySpecialBackground : Boolean = [...]
Column(
    modifier = Modifier
        .fillMaxWidth()
        .conditional(applySpecialBackground) {
            background(Color.Red)
        }
        .conditional(!applySpecialBackground) {
            background(Color.Blue)
        }
        .padding(16.dp)

) { [...] }


如果你觉得自己很棒,你还可以在扩展函数中添加一个可选的否定大小写。

fun Modifier.conditional(
    condition: Boolean,
    ifTrue: Modifier.() -> Modifier,
    ifFalse: (Modifier.() -> Modifier)? = null
): Modifier {
    return if (condition) {
        then(ifTrue(Modifier))
    } else if (ifFalse != null) {
        then(ifFalse(Modifier))
    } else {
        this
    }
}


这将为您的条件为false的情况提供给予一个单独的参数:

val applySpecialBackground : Boolean = [...]
Column(
    modifier = Modifier
        .fillMaxWidth()
        .conditional(
            applySpecialBackground,
            ifTrue = { background(Color.Red) },
            ifFalse = { background(Color.Blue) }
        )
        .padding(16.dp)

) { [...] }


上一个实现中的大thanks to mtotschnig for pointing out a critical bug

euoag5mw

euoag5mw2#

Modifier有一个then函数来连接当前修饰符和另一个修饰符。这个then函数返回一个你没有使用过的新修饰符。你必须用返回的修饰符重新初始化myModifier变量。
检查下面的代码:

var myModifier = Modifier.padding(
    start = 4.dp, end = 4.dp, top = 8.dp, bottom = 8.dp
)

if (viewWidth == null)
  myModifier = myModifier.then(Modifier.fillParentMaxWidth(1f))
else
  myModifier = myModifier.then(Modifier.width(viewWidth))

myModifier = myModifier.then(
  Modifier
    .height(viewHeight ?: 100.dp)
    .clickable(onClick = { listener.onItemClick(item) })
)

字符串

5lwkijsr

5lwkijsr3#

您也可以以更紧凑的方式使用Modifier.then

val modifier = Modifier
            .padding(start = 4.dp, end = 4.dp, top = 8.dp, bottom = 8.dp)
            .then(if(viewWidth == null) Modifier.fillMaxWidth(1f) else Modifier.width(viewWidth))
            .height(viewHeight ?: 100.dp)
            .clickable(onClick = { listener.onItemClick(item) })

字符串
请参阅:https://jetc.dev/slack/2020-12-13-conditional-modifiers.html

ruarlubt

ruarlubt4#

以上所有的答案都很好,但我想补充我的一分钱。我发现这个片段更可读和干净。

ClickableText(
                modifier = Modifier
                    .let {
                        if (selectedPosition == index) {
                            return@let it
                                .background(
                                    Green200,
                                    shape = RoundedCornerShape(12.dp)
                                )

                        }
                        it
                    }
                    .padding(horizontal = 12.dp, vertical = 4.dp),
                text = AnnotatedString(categories[index]),
                style = TextStyle(
                    fontSize = 14.sp,
                    textAlign = TextAlign.Center
                ),
                onClick = {
                    selectedPosition = index
                }
            )

字符串

new9mtju

new9mtju5#

只是以防万一,如果你需要运行组合

@Composable
fun Modifier.conditional(condition: Boolean, modifier: @Composable Modifier.() -> Modifier) =
    then(if (condition) modifier.invoke(this) else this)

字符串

uttx8gqw

uttx8gqw6#

我是根据自己基于https://proandroiddev.com/jetpack-compose-tricks-conditionally-applying-modifiers-for-dynamic-uis-e3fe5a119f45的实现给出答案的
这里没有Modifier特定的东西,这个思想可以推广到任何类。

泛型函数

inline fun <R : Any> R.applyWhen(
    condition: Boolean,
    block: R.() -> R,
): R = applyChoice(condition = condition, trueBlock = block, falseBlock = { this })

inline fun <R : Any> R.applyChoice(
    condition: Boolean,
    trueBlock: R.() -> R,
    falseBlock: R.() -> R,
): R {
    return if (condition) {
        trueBlock()
    } else {
        falseBlock()
    }
}

字符串

用法

val myModifier = Modifier
    .padding(start = 4.dp, end = 4.dp, top = 8.dp, bottom = 8.dp)
    .applyChoice(viewWidth == null, { fillParentMaxWidth(1f) }, { width(viewWidth!!) })
    .height(viewHeight ?: 100.dp)
    .clickable(onClick = { listener.onItemClick(item) })

tkclm6bt

tkclm6bt7#

找到了另一个我觉得更简洁的方法。假设你想根据一个条件向修饰符添加一个“invoke”,你可以使用-

Modifier
    .let { if (condition) it.invoke() else it}

字符串

相关问题