Animate1:animateXXAsState

  • Compose的基础上层高级动画类型:

    • animateFloatAsState
    • animateDpAsState
    • animateSizeAsState
    • animateOffsetAsState
    • animateRectAsState
    • animateIntAsState
    • 等等
  • 上面的这些State,是Compose提供的一些简便实用的场景动画类。可以帮助我们快速实现动画效果。

动画实例:

val pressed by remember { mutableStateOf(false) }
val animateWidthState = animateFloatAsState(//表示从1.0到1.1的点击动画过度State
    if (pressed) {
        1.1f
    } else {
        1.0f
    }
)
Box(
modifier = Modifier
.width(700.dp)
.height(360.dp)
.background(Color.Black)
.clickable {
    pressed = !pressed//点击动态切换mutableState,即会影响animateState
    Toast
        .makeText(
            this@MainActivity,
            "tap this item",
            Toast.LENGTH_LONG
        )
        .show()
}
.scale(animateWidthState.value)
) {  }

结合点击态:

MutableInteractionSource

  • 这个API具备提升组件状态的作用。它允许我们监听制定的组件内部的 [Interaction] 变化

Interaction

  • 表示组件的瞬态 UI 状态。
  • 例如,当Button被按下和释放时,按钮通常会触发 onClick 回调,我们通常希望能够监听到Button的Press等等状态。
  • 比如: PressInteraction.Press,就是Compose中用来表示按下的State。通过Interaction,我们能在对应的状态触发时获得这些状态

Indication

  • 用于制作点击的时候的特殊UI效果的API。material中的水波纹效果,在Compose中,就是实用Indication取制作的。
  • 在本文中,它并不是我们用来做动画的工具(尽管它可以用来做动画,并且能做更多特殊动画,但是本文我们主要讲animateXXAsState的作用)

作用:

  • 上述两种API结合到一起,我们能能够在Button等组件,被按下的时候,获取对应的状态回调,去做特定的动画事件。
  • 比如:Android原生UI的MotionEvent.ACTION_DOWN、MotionEvent.ACTION_UP,我们在监听到这些手势的时候,去对View做一个轻微的放大动画效果。
  • 基于这个,我们用Compose的这两个API来实现看看:

代码示例:

val interactionSource = remember {
    MutableInteractionSource()//remember一个用于提升组件状态的interactionSource
}
val pressed by interactionSource.collectIsPressedAsState()//通过interactionSource,收集Component组件的Press状态
val indication = remember {
    TestIndication //自定义一个indication,Compose的组件有一个DefaultDebugIndication,当没有设置任何Indication的时候,它会自动生效,点击的效果会在View上绘制一个蒙层
}
val animateWidthState = animateFloatAsState(//依然是我们的animate工具,当按下的时候,alpha变成1.1,否则是1.0
    if (pressed) {
        1.1f
    } else {
        1.0f
    }
)
Box(
modifier = Modifier
.width(700.dp)
.height(360.dp)
.clickable(
interactionSource = interactionSource,//这里传入自定义的interactionSource,这样在点击Box这个组件的时候,它的Press等状态就会被提升到interactionSource中。
indication = indication//这里是为了禁用默认的DefaultDebugIndication,当然也可以传入null
) {
    Toast
        .makeText(
            this@MainActivity,
            "tap this item",
            Toast.LENGTH_LONG
        )
        .show()
}
.scale(animateWidthState.value)
) {
    Text("Test Code For Animate")
}


object TestIndication : Indication {
    private class TestIndicationInstance(
        private val isPressed: State<Boolean>,//提供Press的状态
        private val isHovered: State<Boolean>,//提供Hovered的状态
        private val isFocused: State<Boolean>,//提供Focused的状态
    ) : IndicationInstance {
        override fun ContentDrawScope.drawIndication() {
            drawContent()//这里什么也不做,调用drawContent()会把对应点击的View,做一个绘制(当然在这里,我们也可以调用到canvas去做很多其他绘制,这个在本文暂且不表)
        }
    }

    @Composable
    override fun rememberUpdatedInstance(interactionSource: InteractionSource): IndicationInstance {
        val isPressed = interactionSource.collectIsPressedAsState()//同样的,这个函数回调的时候,我们可以拿到一个InteractionSource,可以获取Box组件的UI状态。
        val isHovered = interactionSource.collectIsHoveredAsState()
        val isFocused = interactionSource.collectIsFocusedAsState()
        return remember(interactionSource) {
            TestIndicationInstance(isPressed, isHovered, isFocused)
        }
    }
}

 评论