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

SwiftUI主屏幕小组件Text使用underline()时下划线断裂如何解决

问题原因

这是WidgetKit自iOS14起就存在的渲染层系统bug:小组件运行在独立的渲染进程中,和主App的SwiftUI渲染逻辑并不完全一致,内置的.underline()修饰符在绘制下划线时,无法正确处理字偶距、字形降部(g/y/p等字母的下伸区域)、行高的计算,最终出现下划线分段断裂的表现。该问题和业务侧的参数配置无关,调整字体、字号、基线偏移都只能临时改变错位程度,无法彻底修复。

解决方案

iOS15+ 推荐方案:富文本原生渲染

直接放弃.underline()修饰符,通过AttributedString给文本设置下划线属性,该链路走CoreText底层绘制逻辑,不会出现断裂问题,且天然支持多行自动换行、动态字体、多语言字形适配,不需要手动计算任何布局参数,稳定性最高。

struct NotLoggedInSmallView: View {
    private var underlinedContent: AttributedString {
        var attrText = AttributedString("Ready to write a new chapter in travel?")
        attrText.underlineStyle = .single
        // 可按需自定义下划线颜色,默认与文字 foregroundColor 一致
        // attrText.underlineColor = .accentColor
        return attrText
    }
    
    var body: some View {
        Text(underlinedContent)
            // 此处可正常添加.font/.foregroundColor等文本修饰符,不会影响下划线效果
            .font(.system(size: 14))
    }
}

iOS14 兼容方案

iOS14的Text组件不支持直接传入AttributedString,可以通过UIViewRepresentable封装UILabel实现带下划线的文本,小组件内的静态视图封装不会产生额外性能开销,同样支持多行自适应:

struct UnderlinedText: View {
    private let content: String
    private let font: UIFont
    
    init(_ content: String, font: UIFont = .systemFont(ofSize: 14)) {
        self.content = content
        self.font = font
    }
    
    var body: some View {
        WrappedLabel(content: content, font: font)
    }
    
    private struct WrappedLabel: UIViewRepresentable {
        let content: String
        let font: UIFont
        
        func makeUIView(context: Context) -> UILabel {
            let label = UILabel()
            label.numberOfLines = 0
            label.lineBreakMode = .byWordWrapping
            return label
        }
        
        func updateUIView(_ label: UILabel, context: Context) {
            label.attributedText = NSAttributedString(
                string: content,
                attributes: [
                    .font: font,
                    .underlineStyle: NSUnderlineStyle.single.rawValue
                ]
            )
        }
    }
}

// 调用方式
struct NotLoggedInSmallView: View {
    var body: some View {
        UnderlinedText("Ready to write a new chapter in travel?")
    }
}
避坑提示
  • 不要尝试通过调整baselineOffset、lineSpacing等布局参数修复.underline()的断裂问题,这类调整仅能适配单一固定字号,切换动态字体、系统版本后大概率会再次出现错位
  • 手动在文本下方绘制横线的方案仅适用于固定宽度的单行文本,多行场景下无法自动匹配换行后的行位置,适配成本极高,不推荐使用。

内容的提问来源于stack exchange,提问作者Kirby Todd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:30:43