SwiftUI弹出动画在真机上导致文字抖动问题求助
SwiftUI文字动画真机抖动问题解决方案
问题描述
我在SwiftUI中实现了一个包含文字与图片的弹出动画,模拟器预览显示正常,但真机运行时文字会出现明显抖动,图片动画却表现正常。尝试过移除阴影、调整动画幅度等操作,问题仍未解决。
问题演示:
相关代码
struct SplashScreenContent: View { @State private var blurRadius: CGFloat = 10 @State private var movingShadowX: CGFloat = 4 @State private var movingShadowY: CGFloat = 4 @State private var imageSize: CGFloat = 50 @State private var fontSize: CGFloat = 55 @State private var bottomInset: CGFloat = -5 @State private var trailingInset: CGFloat = -3 var body: some View { VStack { Button("Animate", action: buttonPress) Spacer() VStack(spacing: 45) { Image(systemName: "house") .resizable() .foregroundColor(.white) .scaledToFill() .frame(width: imageSize, height: imageSize) .shadow(color: .black, radius: 1.5) .shadow(color: .yellow, radius: 5) .shadow(color: .black, radius: 3, x: movingShadowX, y: movingShadowY) Text("I'm so\nShakey") .font(.custom("NewYork-regular", size: fontSize)) .fontWeight(.semibold) .foregroundColor(Color.white) .multilineTextAlignment(.center) .padding(.bottom, 70.0) .shadow(color: .black, radius: 1.5) .shadow(color: .yellow, radius: 5) .shadow(color: .black, radius: 3, x: movingShadowX, y: movingShadowY) } .padding(.init(top: 0, leading: 0, bottom: bottomInset, trailing: trailingInset)) .blur(radius: blurRadius) .onAppear(perform: animate) Spacer() } } } extension SplashScreenContent { func buttonPress() { blurRadius = 10 movingShadowX = 4 movingShadowY = 4 imageSize = 50 fontSize = 55 bottomInset = -5 trailingInset = -3 animate() } func animate() { withAnimation(.easeIn(duration: 0.4).delay(0.8)) { blurRadius = 0 withAnimation(.easeIn(duration: 4).delay(0.3)) { movingShadowX = 6 movingShadowY = 9.5 imageSize = 53 fontSize = 58 bottomInset = 13 trailingInset = 3 withAnimation(.easeIn(duration: 0.5).delay(4.3)) { blurRadius = 20 } } } } }
解决办法
1. 替换文字缩放方式
直接动画fontSize会导致真机上自定义字体的浮点精度渲染偏差,改用scaleEffect基于矢量缩放文本:
Text("I'm so\nShakey") .font(.custom("NewYork-regular", size: 55)) // 固定基础字号 .scaleEffect(fontSize / 55) // 用比例缩放代替直接改字号 .fontWeight(.semibold) .foregroundColor(Color.white) .multilineTextAlignment(.center) .padding(.bottom, 70.0) .shadow(color: .black, radius: 1.5) .shadow(color: .yellow, radius: 5) .shadow(color: .black, radius: 3, x: movingShadowX, y: movingShadowY)
2. 拆分嵌套动画
多层嵌套的withAnimation可能导致UI更新不同步,拆分成顺序执行的独立动画块:
func animate() { // 第一步:移除模糊 withAnimation(.easeIn(duration: 0.4).delay(0.8)) { blurRadius = 0 } // 第二步:执行缩放和位移动画(等待第一步结束后启动) withAnimation(.easeIn(duration: 4).delay(1.2)) { movingShadowX = 6 movingShadowY = 9.5 imageSize = 53 fontSize = 58 bottomInset = 13 trailingInset = 3 } // 第三步:添加模糊(等待第二步结束后启动) withAnimation(.easeIn(duration: 0.5).delay(5.2)) { blurRadius = 20 } }
3. 合并文字渲染层
多层阴影叠加会增加真机渲染负担,用compositingGroup()将文字和阴影打包成单个渲染层:
Text("I'm so\nShakey") // 原有属性... .shadow(color: .black, radius: 1.5) .shadow(color: .yellow, radius: 5) .shadow(color: .black, radius: 3, x: movingShadowX, y: movingShadowY) .compositingGroup() // 合并渲染层
4. 优化布局偏移精度
避免用浮点值控制padding偏移,改用offset或使用整数偏移值:
// 替换原有padding .offset(x: trailingInset, y: bottomInset)
内容的提问来源于stack exchange,提问作者CodingLamb
相关产品推荐
相关产品推荐

