如何在SwiftUI中更改超链接文本颜色

6

我正在尝试使用SwiftUI来自定义更改给定Markdown字符串中超链接的默认字体颜色。相当于UIKit中的txtString.linkTextAttributes = [ .foregroundColor: UIColor.red ]

这是我的代码:


import SwiftUI

struct TextViewAttributedString: View {
    var markdownString: String
    var body: some View {
        Text(convertIntoAttributedString(markdownString:markdownString))
    }
    
    private func convertIntoAttributedString(markdownString: String) -> AttributedString {
        guard var attributedString = try? AttributedString(
            markdown: markdownString,
            options: AttributedString.MarkdownParsingOptions(allowsExtendedAttributes: true,
                                                             interpretedSyntax: .inlineOnlyPreservingWhitespace))
        else {
            return AttributedString(markdownString)
        }
        attributedString.font = .custom("Times New Roman", size: 16, relativeTo: .body)
        
        let runs = attributedString.runs
        for run in runs {
            let range = run.range
            if let textStyle = run .inlinePresentationIntent {
                if textStyle.contains(.stronglyEmphasized) { // .stronglyEmphasized is available
                    // change foreground color of bold text
                    attributedString[range].foregroundColor = .green
                }
                if textStyle.contains(.linkTextAttributes) { // compiler error since .linkTextAttributes not available
                    // change color here but .linkTextAttributes is not available in inlinePresentationIntent
                    // Any other way to change the hyperlink color?
                }
            }
        }
        return attributedString
    }
}

应用了AttribtedString的示例视图

import SwiftUI

struct AttributedStringView: View {
    let text: String = "**Bold** regular and _italic_ \nnewline\n[hyperlink](www.google.com)"
    var body: some View {
        TextViewAttributedString(markdownString: text)
    }
}

struct AttributedStringView_Previews: PreviewProvider {
    static var previews: some View {
        AttributedStringView()
    }
}

结果: 结果屏幕

参考文档:https://developer.apple.com/documentation/foundation/attributedstring https://developer.apple.com/videos/play/wwdc2021/10109/


1
请查看这篇 Stack Overflow 的帖子/答案:https://dev59.com/88Lra4cB1Zd3GeqPU--J - workingdog support Ukraine
2
是的,我之前查看了这篇帖子,但那里的解决方案是简单地更改整个字符串的强调颜色。我的情况需要仅将颜色应用于作为字符串一部分的Markdown链接。谢谢。 - Vijay Lama
5个回答

7

对我来说最简单的解决方案是:

 Text(.init("some text **[google.com](https://google.com)**"))
     .accentColor(.red)
                                      

简单的解决方案,效果很好。 - Alwin Jose

4
        if run.link != nil {
            // change foreground color of link
            attributedString[range].foregroundColor = .orange
        }

由于某些原因,这对我不起作用。链接在运行中被识别,但更改颜色没有任何效果。我能够更改背景颜色或字体,但前景颜色和下划线样式保持不变 :( - igr
在我的情况下,@igr链接甚至无法在运行中被识别... - vigdora
1
@igr不起作用,因为inlinePresentationIntent中没有识别出链接。 应该使用=>如果let textStyle = run.link { someCode } - vigdora

2

我不得不替换AttributeContainer。

if run.link != nil {
    var container = AttributeContainer()
    container.foregroundColor = .red
    attributedString[range].setAttributes(container)
}

0

iOS 15: 您可以使用AttributedString初始化SwiftUI的Text。您可以从Markdown字符串创建AttributedString,使用正则表达式查找链接标签,并更改AttributedString的该部分颜色。

let markdown = "**Bold** regular and _italic_ [hyperlink cool](www.google.com)"
let linkColor = UIColor.green

var body: some View {
    Text(makeAttributedString())
}

func makeAttributedString() -> AttributedString {
    var string = (try? AttributedString(markdown: markdown)) ?? AttributedString("Error markdown")
    let linkLabels = getLinkLabels(markdownString: markdown)
    for label in linkLabels {
        if let range = string.range(of: label) {
            string[range].foregroundColor = linkColor
        }
    }
    return string
}

func getLinkLabels(markdownString: String) -> [String] {
    guard let regex = try? NSRegularExpression(pattern: "\\[[a-zA-Z0-9_ ]*\\]") else { return [] }
    let results = regex.matches(in: markdownString,
                                range: NSRange(markdownString.startIndex..., in: markdownString))
    let labels = results.compactMap {
        Range($0.range, in: markdownString).map { String(markdownString[$0]) }
    }
    // removing the brackets from the link labels before return
    return labels.map { $0.trimmingCharacters(in: CharacterSet(charactersIn: "[]")) }
}

非常感谢。这解决了我的问题,我非常感激,但我接受了ChrisR的答案,因为他的答案更加本地化,使用了AttributedString。再次感谢。 - Vijay Lama

-1
对我来说,最简单的解决方案是
Text(verbatim: "email@gmail.com")

我在这里找到了答案。
苹果的文档在这里。

这也将删除链接功能。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接