如何实现指定的图标垂直翻转旋转动画?(附参考资源)
实现Jetpack Compose底部导航图标垂直翻转动画
我需要实现如下GIF展示的图标动画(或许不该叫“垂直旋转”):
我找到过一个底部导航动画示例,但它只是图标弹跳效果,不符合我的需求。我需要的是图标旋转动画,动画过程的中间状态如下:
解决方案
可以通过Jetpack Compose的animateFloatAsState结合Modifier.graphicsLayer的rotationX属性,实现这种垂直翻转的动画效果,核心是控制图标绕X轴的旋转角度,同时在翻转过程中切换图标或调整视觉效果。
双图标翻转实现(切换图标)
这种实现会在翻转到中间状态时,切换显示另一个图标,和你提供的GIF效果一致:
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.filled.Person import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp @Composable fun FlipNavigationIcon() { var isSelected by remember { mutableStateOf(false) } // 动画过渡旋转角度:未选中0°,选中180° val rotationAngle by animateFloatAsState( targetValue = if (isSelected) 180f else 0f, label = "flip rotation" ) Image( // 旋转超过90°时切换图标,模拟翻转显示背面 imageVector = if (rotationAngle > 90f) Icons.Default.Person else Icons.Default.Home, contentDescription = "Navigation icon", modifier = Modifier .size(48.dp) .clickable { isSelected = !isSelected } .graphicsLayer { rotationX = rotationAngle // 调整相机距离,优化透视变形效果 cameraDistance = 8 * density } ) }
单图标翻转实现(仅视觉翻转)
如果不需要切换图标,只需要图标自身的翻转效果,可以用以下代码:
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.material.Icon import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Home import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.unit.dp @Composable fun SingleIconFlip() { var isSelected by remember { mutableStateOf(false) } val rotationAngle by animateFloatAsState( targetValue = if (isSelected) 180f else 0f, label = "single icon flip" ) Icon( imageVector = Icons.Default.Home, contentDescription = "Single flip icon", modifier = Modifier .size(48.dp) .clickable { isSelected = !isSelected } .graphicsLayer { rotationX = rotationAngle cameraDistance = 8 * density // 翻转时调整透明度,增强视觉层次感 alpha = if (rotationAngle > 90f) 0.7f else 1f } ) }
集成到底部导航栏
将上述图标组件替换BottomNavigationItem中的icon参数即可:
import androidx.compose.material.BottomNavigation import androidx.compose.material.BottomNavigationItem import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @Composable fun AnimatedBottomNavigation() { var selectedItem by remember { mutableStateOf(0) } val items = listOf("Home", "Profile") BottomNavigation { items.forEachIndexed { index, item -> BottomNavigationItem( icon = { FlipNavigationIcon() }, label = { Text(item) }, selected = selectedItem == index, onClick = { selectedItem = index } ) } } }
内容的提问来源于stack exchange,提问作者user924
相关产品推荐
相关产品推荐

