微信点赞
compose 点赞效果
动画选择
多状态顺序动画
- 使用
Transition同时为多个属性添加动画效果 Animatable:基于协程顺序动画
拆分动画状态
- INITIAL, // 初始状态(半径0)
- CIRCLE_GROW, // 圆半径增长
- THUMB_UP, // 显示大拇指
- SMALL_CIRCLES, // 周围出现小圆形
- CIRCLES_FADE, // 小圆形消失
- THUMB_FADE // 大拇指消失
代码实战
使用 Transition 管理多状态
使用 Animatable 一样的效果
enum class LikeAnimationState {
INITIAL, // 初始状态(半径0)
CIRCLE_GROW, // 圆半径增长到
THUMB_UP, // 显示大拇指
SMALL_CIRCLES, // 周围出现小圆形
CIRCLES_FADE, // 小圆形消失
THUMB_FADE // 大拇指消失
}
LikeView
@Composable
fun LikeView(start: Boolean) {
//初始状态
var currentState by remember { mutableStateOf(LikeAnimationState.INITIAL) }
//Transition 管理多状态
val transition = updateTransition(targetState = currentState, label = "likeAnimationView")
//圆半径
val density = LocalDensity.current
val radius =
remember {
with(density) {
60.dp.toPx()
}
}
//圆形增长动画
val circleRadius by transition.animateFloat(
transitionSpec = {
tween(
durationMillis = 380,
easing = LinearEasing
)
},
) { state ->
when (state) {
//其他状态 -> CIRCLE_GROW ->其他状态
// 0f-> radius
// radius -> 0f
LikeAnimationState.CIRCLE_GROW -> radius
else -> 0f
}
}
//大拇指
val thumbAlpha by transition.animateFloat(
transitionSpec = {
tween(durationMillis = if (currentState == LikeAnimationState.THUMB_FADE) 1200 else 300)
},
) { state ->
when (state) {
LikeAnimationState.THUMB_UP,
LikeAnimationState.SMALL_CIRCLES,
LikeAnimationState.CIRCLES_FADE -> 1f
else -> 0f
}
}
//周围小圆点
val smallCirclesAlpha by transition.animateFloat(
transitionSpec = { tween(durationMillis = 380) },
) { state ->
when (state) {
LikeAnimationState.SMALL_CIRCLES -> 1f
LikeAnimationState.CIRCLES_FADE -> 0f
else -> 0f
}
}
// 动画序列
LaunchedEffect(start) {
// 初始布局
currentState = LikeAnimationState.INITIAL
delay(100)
//圆环增长
currentState = LikeAnimationState.CIRCLE_GROW
delay(380)
//大拇指出现
currentState = LikeAnimationState.THUMB_UP
delay(100)
//围绕点出现
currentState = LikeAnimationState.SMALL_CIRCLES
delay(380)
//围绕点消失
currentState = LikeAnimationState.CIRCLES_FADE
delay(300)
//大拇指消失
currentState = LikeAnimationState.THUMB_FADE
}
Box(
modifier = Modifier
.size(100.dp)
.background(Color.Transparent),
contentAlignment = Alignment.Center
) {
// 主圆形
if (currentState == LikeAnimationState.CIRCLE_GROW) {
Canvas(modifier = Modifier.matchParentSize()) {
drawCircle(
color = Color.Red.copy(alpha = 0.3f),
radius = circleRadius,
center = center,
style = Stroke(width = radius - circleRadius + 4)
)
}
}
// 大拇指图标
androidx.compose.material3.Icon(
imageVector = Icons.Default.ThumbUp,
contentDescription = "Like",
modifier = Modifier
.size(40.dp)
.alpha(thumbAlpha),
tint = Color.Red
)
// 周围小圆形
if (smallCirclesAlpha > 0f) {
val smallCirclePositions = remember {
List(9) { index ->
val angle = index * (360f / 9)
angle
}
}
val smallCircleColor = remember {
arrayListOf(
Color.Blue, Color.Cyan, Color.Red,
Color.Green, Color.Magenta, Color.Yellow,
Color.LightGray, Color(0xFFBB2EC1),
Color(0xFFC64C45), Color(0xFFFF9800),
)
}
Canvas(modifier = Modifier.matchParentSize()) {
smallCirclePositions.forEachIndexed { index, angle ->
val radians = Math.toRadians(angle.toDouble())
val x =
center.x + 60.dp.toPx() * cos(radians).toFloat()
val y =
center.y + 60.dp.toPx() * sin(radians).toFloat()
drawCircle(
color = smallCircleColor[index].copy(
alpha =
smallCirclesAlpha * 0.8f
),
radius = (smallCirclesAlpha + 0.5f).coerceAtMost(1f) * 6.dp.toPx(),
center = Offset(x, y)
)
}
}
}
}
}