h4rdrew
h4rdrew

Reputation: 41

Crash after migrating to Indication and Ripple APIs in LargeFloatingActionButtonCustom

I recently migrated to the Indication and Ripple APIs as per the official documentation, but after the migration, my application crashes when I click the LargeFloatingActionButtonCustom for the second time, whereas on the first click, the action and ripple occur normally (only when enabled=true).

Here is the error log I receive:

FATAL EXCEPTION: main
Process: br.com.apima.comandaappdroid, PID: 18541
java.lang.IllegalStateException: Could not find delegate: androidx.compose.material.ripple.AndroidRippleNode@e577fcf
    at androidx.compose.ui.node.DelegatingNode.undelegate(DelegatingNode.kt:181)
    at androidx.compose.material3.DelegatingThemeAwareRippleNode.removeRipple(Ripple.kt:362)
    ...
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
    at android.view.Choreographer.doCallbacks(Choreographer.java:952)
    at android.view.Choreographer.doFrame(Choreographer.java:878)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)

After migrating to the new Indication and Ripple APIs, I expected my custom LargeFloatingActionButtonCustom to continue functioning as before, but instead, it crashes when clicked for the second time (enabled=true).

Here is the composable code that I am using:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LargeFloatingActionButtonCustom(
    icon: ImageVector,
    contentDescription: String,
    onClick: () -> Unit,
    enabled: Boolean = true
) {
    CompositionLocalProvider(
        LocalRippleConfiguration provides
                if (enabled) LocalRippleConfiguration.current
                else null
    ) {
        LargeFloatingActionButton(
            modifier = Modifier.size(52.dp),
            shape = CircleShape,
            containerColor = if (enabled) MaterialTheme.colorScheme.primaryContainer else MaterialTheme.colorScheme.surfaceDim,
            onClick = {
                if (enabled) onClick.invoke()
            },
        ) {
            Icon(
                imageVector = icon,
                contentDescription = contentDescription,
                tint = if (enabled)
                    LocalContentColor.current.copy(alpha = LocalContentColor.current.alpha)
                else DarkGray
            )
        }
    }
}

Environment Versions:

I have tried adjusting the LocalRippleConfiguration, but the error persists. How can I resolve this issue?

Upvotes: 4

Views: 142

Answers (2)

Lider
Lider

Reputation: 1

You may try using computed ripple configuration:

val rippleConfiguration = LocalRippleConfiguration.current
val defaultRippleConfiguration = remember { rippleConfiguration }
CompositionLocalProvider(
    LocalRippleConfiguration providesComputed {
        if (rippleEnabled) defaultRippleConfiguration else null
    },
) { ... }

In my case it helped.

Upvotes: 0

captainweeaboo
captainweeaboo

Reputation: 1

Problem is directly related to the conditional LocalRippleConfiguration.

CompositionLocalProvider(
    LocalRippleConfiguration provides
            if (enabled) LocalRippleConfiguration.current
            else null
)

If you reason it, once it disabled, it cannot be reverted to what it actual was before, because its now always null in LocalRippleConfiguration. And when ripple tries to undelegate its node, it cannot be located anymore.

I suggest to refer https://developer.android.com/develop/ui/compose/touch-input/user-interactions/migrate-indication-ripple#globally-change-ripples and provide your own ripple modifier, which can be enabled/disabled at will.

Upvotes: 0

Related Questions