不练不熟,不写就忘 之 compose 之 动画之 animateFloatAsState动画练习
实现效果
- 缩放动画示例:点击按钮实现圆形元素的放大缩小效果,使用scale属性控制尺寸变化
- 透明度动画示例:通过alpha属性控制元素的显示和隐藏,实现淡入淡出效果
- 旋转动画示例:演示如何使用float值控制旋转角度(实际应使用rotate变换)
- 进度条动画示例:展示进度值的平滑过渡,支持多个预设进度值的切换
点击按钮实现圆形元素的放大缩小效果,使用scale属性控制尺寸变化
/*** 点击按钮实现圆形元素的放大缩小效果,使用scale属性控制尺寸变化*/
@Composable
private fun AnimateTest() {var state by remember { mutableStateOf(false) }val animateFloat by animateFloatAsState(targetValue = if(state) 0.5f else 1f,animationSpec = tween(2000))Box(modifier = Modifier.size(100.dp).scale(animateFloat).clip(CircleShape).background(color = Color.Blue).clickable{state = !state})
}

通过alpha属性控制元素的显示和隐藏,实现淡入淡出效果
/*** 通过alpha属性控制元素的显示和隐藏,实现淡入淡出效果*/
@Composable
private fun AnimateTest1() {var state by remember { mutableStateOf(false) }val animateFloat by animateFloatAsState(targetValue = if(state) 0f else 1f,animationSpec = tween(2000))Box(modifier = Modifier.size(100.dp).clip(CircleShape).background(color = Color.Blue.copy(alpha = animateFloat)).clickable{state = !state})
}

使用float值控制旋转角度(实际应使用rotate变换)
@Composable
private fun AnimateTest2() {var state by remember { mutableStateOf(false) }val animateFloat by animateFloatAsState(targetValue = if(state) 360f else 0f,animationSpec = tween(2000))Box(modifier = Modifier.size(100.dp).clip(CircleShape).background(color = Color.Blue).clickable{state = !state},contentAlignment = Alignment.Center){// 绘制表盘刻度Canvas(modifier = Modifier.size(280.dp)) {val center = Offset(size.width / 2, size.height / 2)val radius = size.width / 2 - 10// 绘制刻度for (i in 0 until 12) {val angle = i * 30fval startAngle = Math.toRadians(angle.toDouble()).toFloat()val startX = center.x + radius * 0.8f * kotlin.math.cos(startAngle)val startY = center.y + radius * 0.8f * kotlin.math.sin(startAngle)val endX = center.x + radius * kotlin.math.cos(startAngle)val endY = center.y + radius * kotlin.math.sin(startAngle)drawLine(color = Color.White.copy(alpha = 0.6f),start = Offset(startX, startY),end = Offset(endX, endY),strokeWidth = if (i % 3 == 0) 3f else 1f)}}// 主指针PointerIndicator(modifier = Modifier.size(200.dp).rotate(animateFloat),pointerColor = Color(0xFFFF6B6B),outlineColor = Color(0xFF00FF00),outlineWidth = 2f)}
}@Composable
fun PointerIndicator(modifier: Modifier = Modifier,size: Dp = 100.dp,rotationAngle: Float = 0f,pointerColor: Color = Color.Red,showOutline: Boolean = true,outlineColor: Color = Color.Black,outlineWidth: Float = 2f
) {Canvas(modifier = modifier.size(size).rotate(rotationAngle)) {val centerX = size.toPx() / 2val centerY = size.toPx() / 2val pointerLength = size.toPx() * 0.4fval pointerWidth = size.toPx() * 0.1fval baseWidth = size.toPx() * 0.15f// 创建指针路径val pointerPath = Path().apply {// 指针尖端moveTo(centerX, centerY - pointerLength)// 指针右侧边缘lineTo(centerX + pointerWidth, centerY)// 指针底部右侧lineTo(centerX + baseWidth, centerY)// 指针底部左侧lineTo(centerX - baseWidth, centerY)// 指针左侧边缘lineTo(centerX - pointerWidth, centerY)// 回到尖端闭合路径close()}// 绘制指针填充drawPath(path = pointerPath,color = pointerColor)// 绘制指针轮廓if (showOutline) {drawPath(path = pointerPath,color = outlineColor,style = Stroke(width = outlineWidth))}// 绘制中心圆点drawCircle(color = pointerColor,radius = baseWidth * 0.6f,center = Offset(centerX, centerY))}
}
效果:

@Composable
fun AdvancedRotationAnimation() {var rotationLevel by remember { mutableStateOf(0) }val rotationAngle by animateFloatAsState(targetValue = when (rotationLevel) {1 -> 180f2 -> 360f3 -> 720felse -> 0f},animationSpec = tween(durationMillis = 1500),label = "advanced_rotation")Column(modifier = Modifier.fillMaxSize(),horizontalAlignment = Alignment.CenterHorizontally) {Spacer(modifier = Modifier.height(60.dp))Text(text = "高级旋转控制",style = MaterialTheme.typography.titleLarge,color = MaterialTheme.colorScheme.primary)Spacer(modifier = Modifier.height(40.dp))// 渐变圆形元素Box(modifier = Modifier.size(100.dp).rotate(rotationAngle).clip(CircleShape).background(brush = Brush.linearGradient(colors = listOf(Color(0xFFFF9800), Color(0xFFFF5722)))),contentAlignment = Alignment.Center) {Text(text = "${rotationAngle.toInt()}°",color = Color.White,style = MaterialTheme.typography.bodySmall)}Spacer(modifier = Modifier.height(50.dp))// 多个旋转控制按钮Column(horizontalAlignment = Alignment.CenterHorizontally) {Button(onClick = { rotationLevel = 1 },modifier = Modifier.height(48.dp)) {Text("旋转180°")}Spacer(modifier = Modifier.height(12.dp))Button(onClick = { rotationLevel = 2 },modifier = Modifier.height(48.dp)) {Text("旋转360°")}Spacer(modifier = Modifier.height(12.dp))Button(onClick = { rotationLevel = 3 },modifier = Modifier.height(48.dp)) {Text("旋转720°")}Spacer(modifier = Modifier.height(12.dp))Button(onClick = { rotationLevel = 0 },modifier = Modifier.height(48.dp)) {Text("重置")}}Spacer(modifier = Modifier.height(30.dp))Text(text = "旋转级别: $rotationLevel",style = MaterialTheme.typography.bodyMedium)}
}

进度条动画示例:展示进度值的平滑过渡,支持多个预设进度值的切换
@Composable
fun ProgressAnimationApp() {var currentProgress by remember { mutableStateOf(0f) }val animatedProgress by animateFloatAsState(targetValue = currentProgress,animationSpec = tween(durationMillis = 1000,easing = FastOutSlowInEasing),label = "progress_animation")Column(modifier = Modifier.fillMaxSize().background(brush = Brush.verticalGradient(colors = listOf(Color(0xFF1E3A8A),Color(0xFF0F172A)))).padding(24.dp),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.spacedBy(24.dp),) {// 标题Text(text = "进度动画演示",color = Color.White,fontSize = 28.sp,fontWeight = FontWeight.Bold,textAlign = TextAlign.Center)// 进度显示区域ProgressDisplaySection(progress = animatedProgress,modifier = Modifier.fillMaxWidth())// 预设进度按钮PresetProgressButtons(onProgressSelected = { progress -> currentProgress = progress },modifier = Modifier.fillMaxWidth())// 自定义进度调节CustomProgressSlider(currentProgress = currentProgress,onProgressChanged = { progress -> currentProgress = progress },modifier = Modifier.fillMaxWidth())// 状态信息ProgressInfoSection(progress = animatedProgress,modifier = Modifier.fillMaxWidth())}}@Composable
fun ProgressDisplaySection(progress: Float, modifier: Modifier = Modifier) {Column(modifier = modifier.background(color = Color(0x20FFFFFF),shape = RoundedCornerShape(16.dp)).padding(24.dp),horizontalAlignment = Alignment.CenterHorizontally,verticalArrangement = Arrangement.spacedBy(16.dp)) {// 圆形进度条CircularProgressIndicator(progress = progress,modifier = Modifier.size(120.dp),color = Color(0xFF4ADE80),strokeWidth = 8.dp,trackColor = Color(0x40FFFFFF))// 线性进度条LinearProgressIndicator(progress = progress,modifier = Modifier.fillMaxWidth().height(12.dp),color = Color(0xFF60A5FA),trackColor = Color(0x20FFFFFF))// 进度文本Text(text = "${(progress * 100).toInt()}%",color = Color.White,fontSize = 24.sp,fontWeight = FontWeight.Bold)}
}@Composable
fun PresetProgressButtons(onProgressSelected: (Float) -> Unit,modifier: Modifier = Modifier
) {Column(modifier = modifier.background(color = Color(0x20FFFFFF),shape = RoundedCornerShape(16.dp)).padding(16.dp),verticalArrangement = Arrangement.spacedBy(12.dp)) {Text(text = "预设进度",color = Color.White,fontSize = 18.sp,fontWeight = FontWeight.Medium)Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.spacedBy(12.dp)) {listOf("0%" to 0f,"25%" to 0.25f,"50%" to 0.5f,"75%" to 0.75f,"100%" to 1f).forEach { (label, value) ->Button(onClick = { onProgressSelected(value) },modifier = Modifier.weight(1f),colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF4ADE80))) {Text(label, fontSize = 12.sp)}}}// 特殊进度值Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.spacedBy(12.dp)) {listOf("10%" to 0.1f,"33%" to 0.33f,"66%" to 0.66f,"90%" to 0.9f).forEach { (label, value) ->Button(onClick = { onProgressSelected(value) },modifier = Modifier.weight(1f),colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF60A5FA))) {Text(label, fontSize = 14.sp)}}}}
}@Composable
fun CustomProgressSlider(currentProgress: Float,onProgressChanged: (Float) -> Unit,modifier: Modifier = Modifier
) {Column(modifier = modifier.background(color = Color(0x20FFFFFF),shape = RoundedCornerShape(16.dp)).padding(16.dp),verticalArrangement = Arrangement.spacedBy(16.dp)) {Text(text = "自定义进度调节",color = Color.White,fontSize = 18.sp,fontWeight = FontWeight.Medium)Slider(value = currentProgress,onValueChange = onProgressChanged,modifier = Modifier.fillMaxWidth(),valueRange = 0f..1f,colors = SliderDefaults.colors(thumbColor = Color(0xFFFF6B6B),activeTrackColor = Color(0xFFFF6B6B),inactiveTrackColor = Color(0x40FFFFFF)))Text(text = "当前设置: ${(currentProgress * 100).toInt()}%",color = Color.White.copy(alpha = 0.8f),fontSize = 14.sp)}
}@Composable
fun ProgressInfoSection(progress: Float, modifier: Modifier = Modifier) {Row(modifier = modifier.background(color = Color(0x20FFFFFF),shape = RoundedCornerShape(16.dp)).padding(16.dp),horizontalArrangement = Arrangement.SpaceBetween) {InfoItem("目标进度", "${(progress * 100).toInt()}%")InfoItem("动画状态", if (progress == 0f || progress == 1f) "已完成" else "动画中")InfoItem("持续时间", "1000ms")}
}@Composable
fun InfoItem(label: String, value: String) {Column(horizontalAlignment = Alignment.CenterHorizontally) {Text(text = label,color = Color.White.copy(alpha = 0.6f),fontSize = 12.sp)Text(text = value,color = Color.White,fontSize = 16.sp,fontWeight = FontWeight.Medium)}
}
效果:

布吉岛为什么 绿色按钮的文字没显示出来,十分有九分的迷茫彷徨不知所措!
