前言
本人所有文章中的compose默认指的是compose multiplatform,所以给出的动画效果理论上可以在desktop、android、ios和web上运行,如果特指Android的jetpack compose会单独说明。
背景
上班无聊打开稀土掘金,看到掘友们写出了很多了有意思的效果,所以就想模仿一下。
1.折叠手风琴效果
@Composable
fun AccordionItem(
painter: Painter,
isSelected: Boolean,
onClick: () -> Unit
) {
val width by animateDpAsState(
targetValue = if (isSelected) 300.dp else 100.dp,
animationSpec = tween(1000, easing = FastOutSlowInEasing)
)
val background by animateColorAsState(
targetValue = if (isSelected) Color.LightGray else Color.Gray,
animationSpec = tween(1000, easing = FastOutSlowInEasing)
)
Box(
modifier = Modifier
.padding(8.dp)
.width(width)
.height(200.dp)
.clip(RoundedCornerShape(16.dp))
.clickable { onClick() }
.background(background)
) {
Image(
painter = painter,
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
}
}
@Composable
fun AccordionList(painterList: List<DrawableResource>) {
var selectedIndex by remember { mutableStateOf(1) }
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
painterList.forEachIndexed { index, painter ->
AccordionItem(
painter = painterResource(painter),
isSelected = index == selectedIndex,
onClick = { selectedIndex = if (selectedIndex == index) -1 else index }
)
}
}
}
@Composable
fun AccordionScreen() {
val imageList = listOf(
Res.drawable.tree1,
Res.drawable.tree2,
Res.drawable.tree3,
Res.drawable.tree4
)
MaterialTheme {
Surface {
AccordionList(painterList = imageList)
}
}
}
2.数字增长效果
@Composable
fun AnimatedCounter(targetValue: Int) {
// 使用 animateIntAsState 创建一个动画状态
val animatedValue by animateIntAsState(
targetValue = targetValue,
animationSpec = tween(
durationMillis = 1000,
easing = FastOutSlowInEasing
)
)
// 显示动画化的数字
Text(
text = "$animatedValue",
style = MaterialTheme.typography.h3.copy(fontSize = 50.sp)
)
}
@Composable
fun CounterScreen() {
var counter by remember { mutableIntStateOf(0) }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
AnimatedCounter(targetValue = counter)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = { counter += (1..10000).random() }) {
Text("Increase")
}
}
}
compose实现数字增长很简单,只需要修改这个可变数字,再使用 animateIntAsState 创建一个动画状态,就可以实现。