我有一个应用程序(有一个重复的按钮),我正在更新到Compose 1.4.0,我看到forEachGesture已被弃用。它告诉我使用awaitEachGesture。
我试图迁移我的代码,但我有一个永无止境的循环,因为down。Pressed总是true
这是旧的代码可以工作。
fun Modifier.repeatingClickable(
interactionSource: InteractionSource,
enabled: Boolean = true,
maxDelayMillis: Long = 500,
minDelayMillis: Long = 50,
delayDecayFactor: Float = .20f,
onClick: () -> Unit
): Modifier = composed {
val currentClickListener by rememberUpdatedState(onClick)
pointerInput(interactionSource, enabled) {
forEachGesture {
coroutineScope {
awaitPointerEventScope {
val down = awaitFirstDown(requireUnconsumed = false)
val heldButtonJob = launch {
var currentDelayMillis = maxDelayMillis
while (enabled && down.pressed) {
currentClickListener()
delay(currentDelayMillis)
val nextMillis =
currentDelayMillis - (currentDelayMillis * delayDecayFactor)
currentDelayMillis = nextMillis.toLong().coerceAtLeast(minDelayMillis)
}
}
waitForUpOrCancellation()
heldButtonJob.cancel()
}
}
}
}
}
下面是我的最新尝试。
fun Modifier.repeatingClickable(
interactionSource: InteractionSource,
enabled: Boolean = true,
maxDelayMillis: Long = 500,
minDelayMillis: Long = 50,
delayDecayFactor: Float = .20f,
onClick: () -> Unit
): Modifier = composed {
val currentClickListener by rememberUpdatedState(onClick)
pointerInput(interactionSource, enabled) {
awaitEachGesture {
val down = awaitFirstDown(requireUnconsumed = false)
while (enabled && down.pressed) {
var currentDelayMillis = maxDelayMillis
currentClickListener()
val nextMillis =
currentDelayMillis - (currentDelayMillis * delayDecayFactor)
currentDelayMillis = nextMillis.toLong().coerceAtLeast(minDelayMillis)
}
waitForUpOrCancellation()
}
}
}
我应该如何迁移这个?
要迁移到awaitEachGesture
,将enabled
包裹在rememberUpdatedState
中,并使用之前使用enabled
的变量。然后在awaitEachGesture
中创建一个CoroutineScope
来启动heldButtonJob
。
val currentClickListener by rememberUpdatedState(onClick)
val isEnabled by rememberUpdatedState(enabled)
pointerInput(interactionSource, isEnabled) {
awaitEachGesture {
val down = awaitFirstDown(requireUnconsumed = false)
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val heldButtonJob = scope.launch {
var currentDelayMillis = maxDelayMillis
while (isEnabled && down.pressed) {
currentClickListener()
delay(currentDelayMillis)
val nextMillis =
currentDelayMillis - (currentDelayMillis * delayDecayFactor)
currentDelayMillis = nextMillis.toLong().coerceAtLeast(minDelayMillis)
}
}
waitForUpOrCancellation()
heldButtonJob.cancel()
}
}