第一节-Jetpack Compose 中的自定义动画处理程序
通过自定义动画拥抱动态交互
在本节中,我们将探讨如何使用 Jetpack Compose 中的高级自定义动画处理程序来创建动态和交互式 UI 元素。该示例演示了用户交互如何以有意义的方式影响动画。
示例 - 互动游戏角色运动
我们将通过一个示例来说明这个概念,游戏中的人物(由面部图标表示)会按照用户拖动控制点的路径来确定人物的移动路径。
@Composable
fun GameCharacterMovement() {
val startPosition = Offset(100f, 100f)
val endPosition = Offset(250f, 400f)
val controlPoint = remember { mutableStateOf(Offset(200f, 300f)) }
val position = remember { Animatable(startPosition, Offset.VectorConverter) }
LaunchedEffect(controlPoint.value) {
position.animateTo(
targetValue = endPosition,
animationSpec = keyframes {
durationMillis = 5000
controlPoint.value at 2500 // midway point controlled by the draggable control point
}
)
}
val onControlPointChange: (offset: Offset) -> Unit = {
controlPoint.value = it
}
Box(modifier = Modifier.fillMaxSize()) {
Icon(
Icons.Filled.Face, contentDescription = "Localized description", modifier = Modifier
.size(50.dp)
.offset(x = position.value.x.dp, y = position.value.y.dp)
)
DraggableControlPoint(controlPoint.value, onControlPointChange)
}
}
- GameCharacterMovement为游戏角色的图标设置动画。动画路径由controlPoint控制,用于用户交互设置和更新。
- Animatable用于将图标的位置从 startPosition平滑过渡到endPosition。
- LaunchedEffect监听controlPoint值的变化,每当控制点移动时重新触发动画。
- animationSpec—它是定义动画的持续时间、延迟和缓动的配置。它确定动画值如何随时间变化。
- keyframes— 允许在动画期间指定特定的时间值,从而能够控制动画的中间点。它对于创建复杂的、精心设计的动画特别有用。
- 该keyframes块将动画定义为关键帧序列。在 2500 毫秒(中间点)时,角色到达控制点,然后继续到达结束位置。
Composable
fun DraggableControlPoint(controlPoint: Offset, onControlPointChange: (Offset) -> Unit) {
var localPosition by remember { mutableStateOf(controlPoint) }
Box(
modifier = Modifier
.offset {
IntOffset(
x = localPosition.x.roundToInt() - 15,
y = localPosition.y.roundToInt() - 15
)
}
.size(30.dp)
.background(Color.Red, shape = CircleShape)
.pointerInput(Unit) {
detectDragGestures(onDragEnd = {
onControlPointChange(localPosition)
}) { _, dragAmount ->
// adjust based on screen bounds
val newX = (localPosition.x + dragAmount.x).coerceIn(0f, 600f)
val newY = (localPosition.y + dragAmount.y).coerceIn(0f, 600f)
localPosition = Offset(newX, newY)
}
}
)
}