SwiftUI动态岛紧凑模式:秒表运行时为何占满横向空间?
SwiftUI Dynamic Island紧凑模式秒表显示异常原因分析
在SwiftUI的Dynamic Island紧凑模式下运行秒表时,使用相同的字体与颜色配置,却出现显示差异:
- 空闲状态下秒表显示正常(对应第一张截图)
- 运行状态下Dynamic Island占满整个横向空间(对应第二张截图),预期应保持空闲状态的样式
问题代码片段
compactTrailing中的实现:
if stopwatch.isRunning { // Stopwatch running state Text(timerInterval: stopwatch.timeInterval, countsDown: false) .font(.system(size: 14, weight: .medium)) .foregroundColor(iconTintDarkMode) } else { // Stopwatch idle state Text(timerString(time: stopwatch.elapsedTime)) .font(.system(size: 14, weight: .medium)) .foregroundColor(iconTintDarkMode) }
辅助方法timerString:
func timerString(time: Double) -> String { var result = "" let hours = Int(time) / 3600 let minutes = Int(time) / 60 % 60 let seconds = Int(time) % 60 if hours > 0 { result.append(String(format: "%02d:", hours)) } result.append(String(format: "%02d:%02d", minutes, seconds)) return result }
显示差异原因
两种状态用了不同的Text初始化方式,造成了不一样的布局表现:
- 空闲状态:用
Text(String)创建的视图,会根据字符串实际宽度自动调整大小,只占内容需要的横向空间,符合紧凑模式的预期。 - 运行状态:
Text(timerInterval:countsDown:)这个API生成的文本视图,默认会占满所有可用的横向空间。因为系统考虑到定时器文本宽度会随时间动态变化(比如从“00:00”变到“01:00”再到“10:00”),为了避免频繁调整布局,默认给这个视图开了“最大宽度权限”,导致它撑满了Dynamic Island的横向空间。
修复方案
给运行状态的Text加上.fixedSize()修饰符,强制它根据当前显示的定时器文本宽度来布局,不再占满全部空间:
if stopwatch.isRunning { Text(timerInterval: stopwatch.timeInterval, countsDown: false) .font(.system(size: 14, weight: .medium)) .foregroundColor(iconTintDarkMode) .fixedSize() // 添加这行代码 } else { Text(timerString(time: stopwatch.elapsedTime)) .font(.system(size: 14, weight: .medium)) .foregroundColor(iconTintDarkMode) }
内容的提问来源于stack exchange,提问作者Bar Malka
相关产品推荐
相关产品推荐

