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

Android Jetpack Compose摇摆动画文本抖动问题及平滑优化需求

解决Jetpack Compose摇摆动画中文本抖动问题

问题原因

你的代码中使用rotate修饰符时默认以元素中心为旋转原点,但摇摆动画的支点应该是顶部中心(钉子位置)。默认旋转原点会导致元素旋转时文本的像素对齐出现精度偏差,进而引发抖动;此外,未开启图形层优化也会加重这类问题。

修复方案

  1. 用graphicsLayer替代rotate,显式设置旋转原点为顶部中心(TransformOrigin(0.5f, 0f)),让动画支点与钉子位置完全对齐。
  2. 启用图形层优化标记,减少动画过程中的重绘与布局计算。
  3. 确保文本容器布局稳定,避免旋转触发不必要的布局更新。

修改后的完整代码

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.TransformOrigin
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import network.chaintech.testapplication.ui.theme.TestApplicationTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            Swing()
        }
    }
}

@Composable
fun Swing() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.TopCenter,
    ) {
        Panel()
        Nail(Modifier.align(Alignment.TopCenter))
    }
}

@Composable
fun Panel() {
    val angleOffset = 10f
    val infiniteTransition = rememberInfiniteTransition(label = "")
    val angle by infiniteTransition.animateFloat(
        initialValue = -angleOffset,
        targetValue = angleOffset,
        animationSpec = infiniteRepeatable(
            animation = tween(
                durationMillis = 4000,
                easing = FastOutSlowInEasing
            ),
            repeatMode = RepeatMode.Reverse,
        ), label = ""
    )

    Surface(
        modifier = Modifier
            .size(150.dp)
            .graphicsLayer(
                rotationZ = angle,
                transformOrigin = TransformOrigin(0.5f, 0f),
                optimizationFlags = androidx.compose.ui.graphics.graphicsLayerOptimizeTransform
            ),
        color = Color.Red,
        shape = RoundedCornerShape(8.dp),
    ) {
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Text(
                text = "Hello, Jetpack",
                color = Color.White,
                fontSize = 24.sp,
                fontStyle = FontStyle.Normal,
                modifier = Modifier.padding(5.dp)
            )
        }
    }
}

@Composable
fun Nail(modifier: Modifier) {
    Surface(
        modifier = modifier
            .padding(top = 2.dp)
            .size(32.dp),
        color = Color.Red,
        shape = CircleShape,
        border = BorderStroke(width = 8.dp, color = Color.White)
    ) {}
}

关键修改点说明

  • graphicsLayer(rotationZ = angle):替代rotate,直接在图形层处理旋转,避免布局层面的计算开销。
  • transformOrigin = TransformOrigin(0.5f, 0f):将旋转原点设置为元素顶部水平中心,与钉子位置对齐,消除旋转时的偏移误差。
  • optimizationFlags = androidx.compose.ui.graphics.graphicsLayerOptimizeTransform:启用变换优化,让动画更平滑,减少抖动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 13:02:23