https://kotlinlang.org logo
Title
x

xxfast

05/04/2022, 2:18 AM
is there a neater way to conditionally apply modifiers than
modifier = modifier
  .let { if(canBeExpanded) it.clickable { expanded = !expanded } else it }
f

Francesc

05/04/2022, 2:19 AM
you can use
then
,
modifier = modifier.then(
   if (condition) Modifier.clickable {} else MOdifier
)
x

xxfast

05/04/2022, 2:23 AM
not sure if that's any neater though
modifier = modifier
  .then( if(canBeExpanded) Modifier.clickable { expanded = !expanded } else Modifier)
  .run { if(canBeExpanded) clickable { expanded = !expanded } else this }
trying to avoid that
else
part,
apply
compiles but doesn't seem to work, not sure why
.apply { if(canBeExpanded) clickable { expanded = !expanded } }
f

Francesc

05/04/2022, 2:30 AM
if you have complex logic, you might want to consider an extension function, or using
composed
for simple logic
then
seems to be the preferred approach, if you check the compose code that's what it uses under the hood, for instance
@Stable
@Suppress("ModifierInspectorInfo")
fun Modifier.fillMaxWidth(/*@FloatRange(from = 0.0, to = 1.0)*/ fraction: Float = 1f) =
    this.then(if (fraction == 1f) FillWholeMaxWidth else createFillWidthModifier(fraction))
👍 1
x

xxfast

05/04/2022, 2:34 AM
Extension like this
fun Modifier.on(condition: Boolean, block: Modifier.() -> Modifier): Modifier =
  if(condition) block() else this
can make the call site look like
modifier = modifier
  .on(canBeExpanded) { clickable { expanded = !expanded } }
but this comes at the cost of indirection i guess
f

Francesc

05/04/2022, 2:36 AM
in your particular case, couldn't you always have the clickable modifier and then use
enabled
to control whether it's actually clickable?
x

xxfast

05/04/2022, 2:36 AM
how so?
f

Francesc

05/04/2022, 2:37 AM
using this version of
clickable
fun Modifier.clickable(
    enabled: Boolean = true,
    onClickLabel: String? = null,
    role: Role? = null,
    onClick: () -> Unit
)
with
enabled = condition
x

xxfast

05/04/2022, 2:38 AM
ah much simpler 👍 thanks
👍 1
a

agrosner

05/04/2022, 1:42 PM
/**
 * Convenience for modifiers that should only apply if [condition] is true.
 * [elseFn] useful for conditional else-logic.
 */
inline fun Modifier.thenIf(
    condition: Boolean,
    modifierFn: Modifier.() -> Modifier,
) = this.let {
    if (condition) {
        it.modifierFn()
    } else {
        it
    }
}


/**
 * Convenience for modifiers that should only apply if [condition] is true.
 * [elseFn] useful for conditional else-logic.
 */
inline fun Modifier.thenIf(
    condition: Boolean,
    modifierFn: Modifier.() -> Modifier,
    elseFn: Modifier.() -> Modifier,
) = this.let {
    if (condition) {
        it.modifierFn()
    } else {
        it.elseFn()
    }
}
we use these functions extensively for this specific use case
c

Colton Idle

05/04/2022, 8:16 PM
I asked about something similar a while back: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1638332547357800
z

Zach Klippenstein (he/him) [MOD]

05/10/2022, 3:03 PM
For the record,
apply
doesn't work because apply returns its receiver, not the last expression in the lambda. You'd want
run
or
let
.
2