https://kotlinlang.org logo
#compose
Title
# compose
x

xxfast

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

Francesc

05/04/2022, 2:19 AM
you can use
then
,
Copy code
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
Copy code
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
Copy code
.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
Copy code
@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
Copy code
fun Modifier.on(condition: Boolean, block: Modifier.() -> Modifier): Modifier =
  if(condition) block() else this
can make the call site look like
Copy code
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
Copy code
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
Copy code
/**
 * 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
32 Views