You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jetpack Compose:如何实现带动画的多选项悬浮操作按钮?

实现目标多选项悬浮操作按钮(FAB)动画效果

我想要实现带有如下动画效果的多选项悬浮操作按钮(FAB):
目标动画效果

目前已完成多选项FAB的基础搭建,但无法实现目标动画效果,当前实现效果如下:
当前动画效果

以下是修改后的完整代码,可实现目标动画:


修改后的FilterFabMenu

@Composable
fun FilterFabMenu(
    visible: Boolean,
    items: List<FilterFabMenuItem>,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier.fillMaxWidth(),
        horizontalAlignment = Alignment.End,
        verticalArrangement = Arrangement.spacedBy(16.dp),
    ) {
        items.forEachIndexed { index, menuItem ->
            // 每个菜单项递增延迟,实现依次弹出/收起
            val enterDelay = index * 50
            val exitDelay = (items.size - 1 - index) * 50

            AnimatedVisibility(
                visible = visible,
                enter = slideInVertically(
                    initialOffsetY = { it },
                    animationSpec = tween(200, delayMillis = enterDelay, easing = FastOutSlowInEasing)
                ) + fadeIn(
                    animationSpec = tween(200, delayMillis = enterDelay, easing = FastOutSlowInEasing)
                ) + scaleIn(
                    initialScale = 0.8f,
                    animationSpec = tween(200, delayMillis = enterDelay, easing = FastOutSlowInEasing)
                ),
                exit = slideOutVertically(
                    targetOffsetY = { it },
                    animationSpec = tween(200, delayMillis = exitDelay, easing = FastOutSlowInEasing)
                ) + fadeOut(
                    animationSpec = tween(200, delayMillis = exitDelay, easing = FastOutSlowInEasing)
                ) + scaleOut(
                    targetScale = 0.8f,
                    animationSpec = tween(200, delayMillis = exitDelay, easing = FastOutSlowInEasing)
                )
            ) {
                FilterFabMenuItem(
                    menuItem = menuItem,
                    onMenuItemClick = {}
                )
            }
        }
    }
}

修改后的FilterView

@Composable
fun FilterView(
    items: List<FilterFabMenuItem>,
    modifier: Modifier = Modifier
) {
    var filterFabState by rememberSaveable {
        mutableStateOf(FilterFabState.COLLAPSED)
    }

    val transition = updateTransition(targetState = filterFabState, label = "fab_transition")

    val iconRotationDegree by transition.animateFloat(
        transitionSpec = { tween(durationMillis = 200, easing = FastOutSlowInEasing) },
        label = "rotation"
    ) { state ->
        if (state == FilterFabState.EXPANDED) 230f else 0f
    }

    Column(
        modifier = modifier.fillMaxSize().padding(16.dp),
        horizontalAlignment = Alignment.End,
        verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.Bottom)
    ) {
        FilterFabMenu(items = items, visible = filterFabState == FilterFabState.EXPANDED)
        FilterFab(
            state = filterFabState,
            rotation = iconRotationDegree,
            onClick = { newState ->
                filterFabState = newState
            }
        )
    }
}

关键改动说明

  • 逐个菜单项动画:将AnimatedVisibility从整个Column移至每个FilterFabMenuItem外层,通过索引计算延迟,实现菜单从上到下依次弹出、从下到上依次收起的递进效果
  • 动画组合优化:使用滑动+缩放+透明度的组合动画,替代原来的整体展开/收起,匹配目标效果的细腻过渡
  • 状态绑定修复:简化updateTransition的使用,直接关联filterFabState,确保主FAB的旋转动画与菜单状态完全同步
  • 动画参数调整:设置200ms动画时长、50ms项级延迟,让动画过渡更自然流畅

内容的提问来源于stack exchange,提问作者Jarnojr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 14:35:40