Customize the click animation on Compose UI



First,  create a state to trigger the animation from start to end.

there using the function pointerInput to detect the gestures:


  Modifier
    .pointerInput(key1 = this) { // block 
    awaitPointerEventScope {
    while (true) {
    buttonState = if (buttonState == ButtonState.Pressed) {
    waitForUpOrCancellation(PointerEventPass.Initial)
    ButtonState.Idle
    } else {
    awaitFirstDown(true)
    ButtonState.Pressed
    }
    }
    }
  }

key1 is a value that involves the `block` that should be re-executed when its content changes. (and the previous `block` will be canceled.)
- when we set the `this` keyword as key1 variable, we suppose to know this `block` executed once only. 
- inside the `awaitPointerEventScope`, we should run a while loop always to prevent leaving this code.  

awaitFirstDown is a suspend function waiting for the action down event from the user.

and... if A and B are buttons like below:
requireUnconsumed set to 

`true` will let you receive the event touched on A except on B. 
`false` will let you receive the event both touched on the A and B. 

- the annotation is we can't write this code above a `clickable` function, the event will be consumed by that `clickable` function.

🆇 DON'T
  Modifier
.pointerInput(this) { /* ... */ }
.clickable { /* ... */ }

🆅 DO
  Modifier
.clickable { /* ... */ }
.pointerInput(this) { /* ... */ }

Animate the values

Now, we can create the Transition object from this button state. or use animaxxToState APIs to create custom animations.

    var buttonState by remember { mutableStateOf(ButtonState.Idle) }
    val transition = updateTransition(targetState = buttonState,                                      label = "buttonState")
a shadow animation will look like this:

    val animatedElevation by transition.animateDp(
    targetValueByState = { if (it == ButtonState.Pressed) 0.dp                                else elevationSize },
    label = ""
    )
use animatedElevation to shadow function
  
  Modifier
    .shadow(
    animatedElevation,
    CardDefaults.shape,
    ambientColor = MaterialTheme.colorScheme.surface,
    spotColor = ShadowGray
    )

Wrapper this function as an extension of the Modifier


    fun Modifier.animateBouncePress(elevationSize: Dp) = composed(
    inspectorInfo = debugInspectorInfo {
     name = "animateBouncePress"
     properties["elevationSize"] = elevationSize
}) { /* the implement */ }     

留言

熱門文章