📐

Jetpack Composeでdebounceなclickableの実装

2022/07/08に公開

概要

Jetpack Composeにおいて、短期間に連打されたとしても1回のみ処理を行う debouncedClickable を実装する。

環境

  • Kotlin 1.6.10
  • Jetpack Compose 1.1.1

実装

// InvokeThrottle.kt
class InvokeThrottle(
  private val coolTimeMs: Long,
  private val call: () -> Unit
) {
  private var lastInvokedAt: Long = 0L

  operator fun invoke() {
    val now = System.currentTimeMillis()
    if (now - lastInvokedAt > coolTimeMs) {
      call()
      lastInvokedAt = now
    }
  }
}
// ModifierExt.kt
fun Modifier.debouncedClickable(
  coolTimeMs: Long = 500L, // クールタイムをミリ秒で指定する
  enabled: Boolean = true,
  onClickLabel: String? = null,
  role: Role? = null,
  onClick: () -> Unit,
) = composed(
  inspectorInfo = debugInspectorInfo {
    name = "clickable"
    properties["enabled"] = enabled
    properties["onClickLabel"] = onClickLabel
    properties["role"] = role
    properties["onClick"] = onClick
  }
) {
  val invokeThrottle = remember { InvokeThrottle(coolTimeMs, onClick) }

  Modifier.clickable(
    enabled = enabled,
    onClickLabel = onClickLabel,
    onClick = invokeThrottle::invoke,
    role = role,
    indication = LocalIndication.current,
    interactionSource = remember { MutableInteractionSource() }
  )
}

参考

https://al-e-shevelev.medium.com/how-to-prevent-multiple-clicks-in-android-jetpack-compose-8e62224c9c5e

Discussion