Jetpack ComposeでonClickのrippleエフェクトを止めたい
Jetpack ComposeのModifier.clickableを使うと自動的にリップルエフェクト(タップした点から波紋が広がるようなエフェクト)が有効になります。今回はこのリップルエフェクトを無効にする方法を紹介します。
やりたいこと

こんな感じで、リップルエフェクトを無効にします。
サンプル
ソースコードはGitHubにあります。
主な環境は以下の通りです。
- Kotlin 1.7210
- Compose Compiler 1.3.2
- Compose Libraries 1.2.1
- Material3 1.0.0-rc01
- Accompanist 0.25.1
二つのModifier.clickable
標準のclickableには引数が少ないバージョンと引数が多いバージョンがあります。
fun Modifier.clickable( enabled: Boolean = true, onClickLabel: String? = null, role: Role? = null, onClick: () -> Unit): Modifierfun Modifier.clickable( interactionSource: MutableInteractionSource, indication: Indication?, enabled: Boolean = true, onClickLabel: String? = null, role: Role? = null, onClick: () -> Unit): ModifierシンプルにModifier.clickable { ... }という書き方をした時に呼び出されるのは、引数が少ない方です。引数が少ない方のclickableは、内部で引数が多い方を呼び出します。その時にindicationにLocalIndicationを渡しているので、デフォルトではリップルエフェクトが発生します。
リップルエフェクトを無効にするには、引数が多い方のclickableにindication = nullを指定すればOKです。interactionSourceにはremember { MutableInteractionSource() }を指定するのが定型です。
Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = null,) { // onClickの処理}Modifierの拡張関数を作る
以下のようにModifierの拡張関数を作っておくと、使いまわせて便利です。
fun Modifier.clickableNoRipple( enabled: Boolean = true, onClickLabel: String? = null, role: Role? = null, onClick: () -> Unit,): Modifier = composed { this.clickable( interactionSource = remember { MutableInteractionSource() }, indication = null, enabled = enabled, onClickLabel = onClickLabel, role = role, onClick = onClick )}ポイントは、composedです。Developer Guideには以下のように説明されています。
変更する要素ごとに、コンポーズされる
Modifierのジャストインタイム コンポジションを宣言します。https://developer.android.com/jetpack/compose/modifiers-list?hl=ja
ちょっと日本語が難しいですが、、、要するに、状態を持つModifierを複数個所で同時に使っても問題ないようにしてくれる、ということだと思います。今回の場合はremember { MutableInteractionSource() }の部分が状態(ステートフル)ですね。
サンプルソース
冒頭の動画のサンプルソースはこんな感じです。一つ目のコンポーザブルには、標準の引数が少ない方のclickableを使っているので、リップルエフェクトが発生します。二つ目のコンポーザブルには、先ほど作ったclickableNoRippleを使っているので、リップルエフェクトが無効になります。
@Composablefun NoRippleEffectSample() { Column( ... ) { var text1 by remember { mutableStateOf("Click me") } var text2 by remember { mutableStateOf("Click me") } ClickMe( title = text1, subTitle = "(Ripple effect)", color = MaterialTheme.colorScheme.secondary, modifier = Modifier.clickable { text1 += "!" } ) ClickMe( title = text2, subTitle = "(No ripple effect)", color = MaterialTheme.colorScheme.tertiary, modifier = Modifier.clickableNoRipple { text2 += "!" } ) }}ClickMeの中身なども含めてソースコードを見たい方は、GitHubを参照してください。
