SwiftUI文本子串动画:如何保持统一字号并支持自动换行?
SwiftUI 统一文本字号并保留切换动画解决方案
你的问题根源在于:每个独立的Text组件都有自己的缩放逻辑,当空间不足时会各自独立缩放,导致字号不一致。以下是两种直接可行的解决方法:
方案一:合并为单个Text(推荐,支持自动换行+统一字号)
将静态文本和动态文本拼接成一个完整的Text组件,让所有文本共享同一布局上下文,彻底解决字号不一致问题,同时保留动态部分的切换动画。
import SwiftUI struct ContentView: View { let array = ["lecture", "conversation", "meeting"] @State private var currentIndex = 0 @State private var currentWord = "" // 使用SwiftUI原生定时器,适配生命周期 private let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect() var body: some View { VStack { // 拼接为单个完整Text,确保字号、缩放、换行规则统一 (Text("Transform ") + Text(currentWord) .transition(.opacity.combined(with: .scale)) // 淡入淡出+缩放动画 + Text(" to Quick Note")) .font(.title) .lineLimit(nil) // 允许自动换行 .minimumScaleFactor(0.5) // 整体缩放,而非单个Text独立缩放 .padding() } .onReceive(timer) { _ in withAnimation(.easeInOut(duration: 1)) { currentIndex = (currentIndex + 1) % array.count currentWord = array[currentIndex] } } .onAppear { currentWord = array[0] } } } #Preview { ContentView() }
关键改动
- 合并所有Text为一个拼接组件,确保所有文本共享相同的字号、缩放和换行规则
- 用
Timer.publish替代原生Timer,避免内存泄漏,适配SwiftUI生命周期 - 用
withAnimation包裹状态更新,确保动态文本切换时有流畅动画 - 移除单个Text的
lineLimit(1),允许整体文本自动换行
方案二:保持HStack结构但统一缩放逻辑
如果需要保留HStack布局,可以通过绑定统一的缩放因子,让所有Text同步缩放:
import SwiftUI struct ContentView: View { let array = ["lecture", "conversation", "meeting"] @State private var currentIndex = 0 @State private var currentWord = "" @ScaledMetric(relativeTo: .title) private var fontSize = 1 private let timer = Timer.publish(every: 2, on: .main, in: .common).autoconnect() var body: some View { VStack { HStack(alignment: .firstTextBaseline, spacing: 4) { Text("Transform") .font(.title.scale(fontSize)) .lineLimit(nil) Text(currentWord) .font(.title.scale(fontSize)) .transition(.opacity) .lineLimit(nil) Text("to Quick Note") .font(.title.scale(fontSize)) .lineLimit(nil) } .padding() .minimumScaleFactor(0.5) .dynamicTypeSize(...DynamicTypeSize.accessibility1) } .onReceive(timer) { _ in withAnimation(.easeInOut(duration: 1)) { currentIndex = (currentIndex + 1) % array.count currentWord = array[currentIndex] } } .onAppear { currentWord = array[0] } } } // 扩展Font支持统一缩放 extension Font { func scale(_ factor: CGFloat) -> Font { self.modifier(FontScaleModifier(scaleFactor: factor)) } } struct FontScaleModifier: ViewModifier { let scaleFactor: CGFloat func body(content: Content) -> some View { content.scaleEffect(scaleFactor) } } #Preview { ContentView() }
说明
- 通过
@ScaledMetric绑定统一缩放因子,确保所有Text同步缩放 - 用
HStack(alignment: .firstTextBaseline)保证文本基线对齐,避免错位 - 保留HStack结构的同时,解决字号不一致问题
内容的提问来源于stack exchange,提问作者Cheok Yan Cheng
相关产品推荐
相关产品推荐

