在 Jetpack Compose 中,当您在可组合项的修饰符上启用
clickable {}
时,默认情况下它会为其启用波纹效果。如何禁用此行为?
示例代码
Row(modifier = Modifier
.clickable { // action }
)
简短回答:
要禁用
null
修改器中
indication
参数中的波纹传递
clickable
:
val interactionSource = remember { MutableInteractionSource() }
Column {
Text(
text = "Click me without any ripple!",
modifier = Modifier
.clickable(
interactionSource = interactionSource,
indication = null
) {
/* doSomething() */
}
)
为什么它不能与某些可组合项一起用作按钮:
请注意,在某些可组合项中,例如
Button
或 IconButton
,它不起作用,因为 indication
是由使用 indication = rememberRipple()
的组件在内部定义的。这将使用 Ripple
提供的值创建并记住 RippleTheme
。
在这种情况下,您无法禁用它,但您可以更改基于
RippleTheme
的波纹的外观。您可以定义自定义 RippleTheme 并使用 LocalRippleTheme
将其应用到您的可组合项。
类似:
CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
Button(
onClick = { /*...*/ },
) {
//...
}
}
与:
private object NoRippleTheme : RippleTheme {
@Composable
override fun defaultColor() = Color.Unspecified
@Composable
override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f,0.0f,0.0f,0.0f)
}
自定义修改器
如果您愿意使用上面相同的代码构建自定义修改器,您可以使用:
fun Modifier.clickableWithoutRipple(
interactionSource: MutableInteractionSource,
onClick: () -> Unit
) = composed(
factory = {
this.then(
Modifier.clickable(
interactionSource = interactionSource,
indication = null,
onClick = { onClick() }
)
)
}
)
然后应用它:
Row(
modifier = Modifier
.clickableWithoutRipple(
interactionSource = interactionSource,
onClick = { doSomething() }
)
){
//Row content
}
clickable
修饰符 添加到可组合项以使其在其范围内可点击,它将显示 Indication
,如指示参数中指定的那样。
LocalIndication
的指示。
如果您在层次结构中使用
MaterialTheme
,则由 Ripple
定义的
rememberRipple()
将用作组件(例如 Indication
和 androidx.compose.foundation.clickable
)内的默认 androidx.compose.foundation.indication
。
使用此修饰符扩展:
fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = composed {
clickable(indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
然后只需将
Modifier.clickable {}
替换为 Modifier.noRippleClickable {}
Row(modifier = Modifier.noRippleClickable {
// action
})
要禁用波纹效果,必须将
null
传递给修改器的 indication
属性。
有关 Jetpack Compose 文档中的指示的更多信息
代码
Row(
modifier = Modifier
.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() } // This is mandatory
) {
// action
}
)
使用按钮时可以这样处理。
创建一个Ripple交互源类
class NoRippleInteractionSource : MutableInteractionSource {
override val interactions: Flow<Interaction> = emptyFlow()
override suspend fun emit(interaction: Interaction) {}
override fun tryEmit(interaction: Interaction) = true
}
如果是按钮,您可以通过将波纹交互类作为 interactionSource 参数传递来处理它,即:
Button(
onClick = { /*...*/ },
interactionSource = NoRippleInteractionSource()
) {
//..
}
此解决方案适用于所有接受 mutableInteractionSource 作为参数的可组合项,例如 Button()、TextButton()、Switch() 等
使用可点击修改器时,您可以这样做:
modifier = Modifier.clickable(
indication = null,
interactionSource = NoRippleInteractionSource()
) { /** todo action here */ }
您还可以进一步修改上述答案并创建扩展函数并重新用于所有可点击的功能,即:
fun Modifier.noRippleClick(onClick:()->Unit):Modifier {
return this.clickable(
interactionSource = NoRippleInteractionSource(),
indication = null
){
onClick()
}
}
您现在可以使用扩展修饰符代替可点击修饰符,即:
modifier = modifier.noRippleClick { /** todo action here */ }
具有其他参数的修饰符扩展:
inline fun Modifier.noRippleClickable(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
crossinline onClick: ()->Unit
): Modifier = composed {
clickable(
enabled = enabled,
indication = null,
onClickLabel = onClickLabel,
role = role,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
创建一个自定义修改器,使可组合项可单击,单击时不会显示波纹效果。
fun Modifier.noRippleClickable(
onClick: () -> Unit
): Modifier = composed {
clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }) {
onClick()
}
}
之后,您可以像下面这样使用它:
modifier = Modifier.noRippleClickable(
onClick = {
}),
我使用了@Mahdi-Malv的答案并修改如下:
fun Modifier.noRippleClickable( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, indication: Indication? = null, enabled: Boolean = true, onClickLabel: String? = null, role: Role? = null, onClick: () -> Unit, ) = clickable( interactionSource = interactionSource, indication = indication, enabled = enabled, onClickLabel = onClickLabel, role = role, onClick = onClick, )
对于
androidx.compose.foundation
,可点击扩展内有一个 enabled
属性。我认为这是最简单的方法。 链接
fun Modifier.clickable(
interactionSource: MutableInteractionSource,
indication: Indication?,
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
): Modifier