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)
}
}
}