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

Jetpack Compose:如何按n倍因子动画放大获焦按钮尺寸

实现焦点驱动的按钮缩放动画(低重组版)

要实现按钮获焦时放大1.2倍、失焦时还原的动画,同时尽可能减少重组,你可以通过记录初始尺寸+缩放动画的方式实现,核心是避免不必要的状态更新和布局变更:

核心思路

  1. 仅在按钮首次布局完成后记录初始尺寸,避免重复触发重组
  2. 使用animateFloatAsState管理缩放比例的动画状态,而非直接修改尺寸
  3. 通过scale modifier应用视觉缩放,不改变布局尺寸,减少布局层面的重组

完整代码实现

@Composable
fun ScalingFocusButton() {
    // 存储按钮初始尺寸,仅首次布局时赋值
    val initialSize = remember { mutableStateOf<Size?>(null) }
    // 焦点状态
    val isFocused = remember { mutableStateOf(false) }
    // 缩放比例动画:获焦时1.2f,失焦时1f
    val scaleFactor by animateFloatAsState(
        targetValue = if (isFocused.value) 1.2f else 1f,
        animationSpec = tween(durationMillis = 300),
        label = "ButtonScaleAnimation"
    )

    Column {
        Button(
            onClick = {},
            modifier = Modifier
                // 记录初始尺寸(仅首次布局时更新)
                .onGloballyPositioned { layoutCoordinates ->
                    if (initialSize.value == null) {
                        initialSize.value = layoutCoordinates.size.toSize()
                    }
                }
                // 监听焦点变化,更新状态
                .onFocusChanged { focusState ->
                    isFocused.value = focusState.isFocused
                }
                // 应用缩放动画(仅视觉层面,不影响布局)
                .scale(scaleFactor)
        ) {
            Text(text = "Focus Me")
        }
    }
}

关键细节说明

  • 初始尺寸记录:onGloballyPositioned会在每次布局变化时触发,但我们通过判断initialSize.value == null,只在首次布局时记录尺寸,避免后续不必要的状态更新和重组。
  • 缩放动画优化:使用scale modifier替代修改尺寸的方式,缩放是在绘制阶段完成的,不会触发布局重组,性能更优;animateFloatAsState会自动处理动画的启停,状态变更仅触发必要的重绘。
  • 状态管理:用remember包裹状态变量,确保重组时状态不会丢失,同时仅在焦点变化时更新isFocused状态,减少无效重组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 01:12:21