如何在 SwiftUI 中创建超链接
How to make hyperlinks in SwiftUI
在Swift中,如图所示,您可以使用"NSMutableAttributedString"在文本中嵌入链接。
如何使用 SwiftUI 实现此目的?
我按如下方式实现了它,但这看起来并不像我想要的那样。 .
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Text("By tapping Done, you agree to the ")
Button(action: {}) {
Text("privacy policy")
}
Text(" and ")
Button(action: {}) {
Text("terms of service")
}
Text(" .")
}
}
}
Motjaba Hosseni 是正确的,到目前为止在 SwiftUI 中没有任何类似于 NSAttributedString 的东西。
这应该可以暂时解决您的问题:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("By tapping Done, you agree to the ")
HStack(spacing: 0) {
Button("privacy policy") {}
Text(" and ")
Button("terms of service") {}
Text(".")
}
}
}
}
在 UIViewRepresentable
中包装 UIKit 视图始终是一个选项。只需通过手动过程公开您要更改的每个属性。
struct AttributedText: UIViewRepresentable {
var attributedText: NSAttributedString
init(_ attributedText: NSAttributedString) {
self.attributedText = attributedText
}
func makeUIView(context: Context) -> UITextView {
return UITextView()
}
func updateUIView(_ label: UITextView, context: Context) {
label.attributedText = attributedText
}
}
//usage: AttributedText(NSAttributedString())
使用内置函数+
,看起来很有魅力:
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Button(action: {
}) {
Text("By tapping Done, you agree to the ")
+ Text("privacy policy")
.foregroundColor(Color.blue)
+ Text(" and ")
+ Text("terms of service")
.foregroundColor(Color.blue)
+ Text(".")
}
.foregroundColor(Color.black)
}
}
}
我知道有点晚了,但我使用 HTML 解决了同样的问题。
首先我创建了一个小助手和 link 模型。
struct HTMLStringView: UIViewRepresentable {
let htmlContent: String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.loadHTMLString(htmlContent, baseURL: nil)
}
}
struct TextLink {
let url: URL
let title: String
}
接下来,我创建了将 String 更改为 HTML 并将第一次出现的 @link 替换为我的可点击 link.
的函数
var content = "My string with @link."
var link = TextLink(url: URL(string: "https://www.facebook.com")!, title: "Facebook")
var body: some View {
let bodySize = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body).pointSize
var html = "<span style=\"font: -apple-system-body; font-size:calc(\(bodySize)px + 1.0vw)\">"
if let linkRange = content.range(of: "@link") {
let startText = content[content.startIndex ..< linkRange.lowerBound]
let endText = content[linkRange.upperBound ..< content.endIndex]
html += startText
html += "<a href=\"\(link.url.absoluteString)\">\(link.title)</a>"
html += endText
} else {
html += content
}
html += "</span>"
return HTMLStringView(htmlContent: html)
}
iOS 15+ (Swift 5.5 +)
SwiftUI 内置支持渲染 Markdown
要创建 link,请将 link 文本括在方括号中(例如,[Duck Duck Go]),然后紧跟在括号中的 URL(例如, (https://duckduckgo.com)).
My favorite search engine is [Duck Duck Go](https://duckduckgo.com).
https://www.markdownguide.org/basic-syntax/#links
使用降价文本作为 Text 的参数。
文本("Privacy Policy")
字符串变量
- 使用
init(_ value: String)
Creates a localized string key from the given string value.
let link = "[Duck Duck Go](https://duckduckgo.com)"
Text(.init(link))
属性文本
- 使用
init(_ attributedContent: AttributedString)
Creates a text view that displays styled attributed content.
let markdownLink = try! AttributedString(markdown: "[Duck Duck Go](https://duckduckgo.com)")
Text(markdownLink)
类似问题:
使用Link视图
A control for navigating to a URL.
https://developer.apple.com/documentation/swiftui/link
Link("Privacy Policy", destination: URL(string: "https://example.com")!)
正如@mahan 提到的那样,通过使用降价语言,这非常适用于 iOS 15.0 及更高版本:
Text("[Privacy Policy](https://example.com)")
但是如果您使用的是 String
变量,并将其放入 Text
中,它将无法工作。示例:
let privacyPolicyText = "Read our [Privacy Policy](https://example.com) here."
Text(privacyPolicyText) // Will not work
使用字符串变量的解决方案
原因是Text
得到了多次启迪。那么我们如何解决这个问题呢?最简单的方法就是:
let privacyPolicyText = "Read our [Privacy Policy](https://example.com) here."
Text(.init(privacyPolicyText))
结果:阅读我们的 Privacy Policy 此处。
使用 LocalizedStringKey 非常简单,例如:
let message = "Hello, www.google.com this is just testing for hyperlinks, check this out our website https://www.apple.in thank you."
Text(LocalizedStringKey(message))
我尝试在中间使用 Link 连接文本,这些是 iOS 15+ 及以下 iOS 15.
if #available(iOS 15, *) {
Text("[Seperate Link 1 ](https://www.android.com/intl/en_in/)")
.font(.caption)
.foregroundColor(Color.green)
// green color is not applied.
Text("[Seperate Link 2 ](https://www.apple.com/in/)")
.font(.caption)
.accentColor(Color.green)
// green is applied.
Text("By authorizing you agree
our ")
.font(.caption)
.foregroundColor(Color.black)
+ Text("[Terms and Conditions](https://www.android.com/intl/en_in/)")
.font(.caption)
.foregroundColor(Color.green) // default blue is applied
+ Text(" and ")
.font(.caption)
.foregroundColor(Color.black)
+ Text("[Privacy Policy](https://www.apple.com/in/)")
.font(.caption)
.foregroundColor(Color.green) // default blue
// cannot use accentColor(Color.green) here
}
else{
// lower iOS versions.
VStack{
Text("By authorizing you agree our ")
.font(.caption)
.foregroundColor(Color.black)
HStack(spacing: 4 ) {
Text("Terms and Conditions")
.font(.caption)
.foregroundColor(Color.green)
.onTapGesture {
let url = URL.init(string: "https://www.android.com/intl/en_in/")
guard let termsAndConditionURL = url, UIApplication.shared.canOpenURL(termsAndConditionURL) else { return }
UIApplication.shared.open(termsAndConditionURL)
}
Text("and")
.font(.caption)
.foregroundColor(Color.black)
Text("Privacy Policy")
.font(.caption)
.foregroundColor(Color.green)
.onTapGesture {
let url = URL.init(string: "https://www.apple.com/in/")
guard let privacyPolicyURL = url, UIApplication.shared.canOpenURL(privacyPolicyURL) else { return }
UIApplication.shared.open(privacyPolicyURL)
}
}
}
}
在Swift中,如图
如何使用 SwiftUI 实现此目的?
我按如下方式实现了它,但这看起来并不像我想要的那样。
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Text("By tapping Done, you agree to the ")
Button(action: {}) {
Text("privacy policy")
}
Text(" and ")
Button(action: {}) {
Text("terms of service")
}
Text(" .")
}
}
}
Motjaba Hosseni 是正确的,到目前为止在 SwiftUI 中没有任何类似于 NSAttributedString 的东西。 这应该可以暂时解决您的问题:
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("By tapping Done, you agree to the ")
HStack(spacing: 0) {
Button("privacy policy") {}
Text(" and ")
Button("terms of service") {}
Text(".")
}
}
}
}
在 UIViewRepresentable
中包装 UIKit 视图始终是一个选项。只需通过手动过程公开您要更改的每个属性。
struct AttributedText: UIViewRepresentable {
var attributedText: NSAttributedString
init(_ attributedText: NSAttributedString) {
self.attributedText = attributedText
}
func makeUIView(context: Context) -> UITextView {
return UITextView()
}
func updateUIView(_ label: UITextView, context: Context) {
label.attributedText = attributedText
}
}
//usage: AttributedText(NSAttributedString())
使用内置函数+
,看起来很有魅力:
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Button(action: {
}) {
Text("By tapping Done, you agree to the ")
+ Text("privacy policy")
.foregroundColor(Color.blue)
+ Text(" and ")
+ Text("terms of service")
.foregroundColor(Color.blue)
+ Text(".")
}
.foregroundColor(Color.black)
}
}
}
我知道有点晚了,但我使用 HTML 解决了同样的问题。 首先我创建了一个小助手和 link 模型。
struct HTMLStringView: UIViewRepresentable {
let htmlContent: String
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.loadHTMLString(htmlContent, baseURL: nil)
}
}
struct TextLink {
let url: URL
let title: String
}
接下来,我创建了将 String 更改为 HTML 并将第一次出现的 @link 替换为我的可点击 link.
的函数var content = "My string with @link."
var link = TextLink(url: URL(string: "https://www.facebook.com")!, title: "Facebook")
var body: some View {
let bodySize = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body).pointSize
var html = "<span style=\"font: -apple-system-body; font-size:calc(\(bodySize)px + 1.0vw)\">"
if let linkRange = content.range(of: "@link") {
let startText = content[content.startIndex ..< linkRange.lowerBound]
let endText = content[linkRange.upperBound ..< content.endIndex]
html += startText
html += "<a href=\"\(link.url.absoluteString)\">\(link.title)</a>"
html += endText
} else {
html += content
}
html += "</span>"
return HTMLStringView(htmlContent: html)
}
iOS 15+ (Swift 5.5 +)
SwiftUI 内置支持渲染 Markdown
要创建 link,请将 link 文本括在方括号中(例如,[Duck Duck Go]),然后紧跟在括号中的 URL(例如, (https://duckduckgo.com)).
My favorite search engine is [Duck Duck Go](https://duckduckgo.com).
https://www.markdownguide.org/basic-syntax/#links
使用降价文本作为 Text 的参数。
文本("Privacy Policy")
字符串变量
- 使用
init(_ value: String)
Creates a localized string key from the given string value.
let link = "[Duck Duck Go](https://duckduckgo.com)"
Text(.init(link))
属性文本
- 使用
init(_ attributedContent: AttributedString)
Creates a text view that displays styled attributed content.
let markdownLink = try! AttributedString(markdown: "[Duck Duck Go](https://duckduckgo.com)")
Text(markdownLink)
类似问题:
使用Link视图
A control for navigating to a URL.
https://developer.apple.com/documentation/swiftui/link
Link("Privacy Policy", destination: URL(string: "https://example.com")!)
正如@mahan 提到的那样,通过使用降价语言,这非常适用于 iOS 15.0 及更高版本:
Text("[Privacy Policy](https://example.com)")
但是如果您使用的是 String
变量,并将其放入 Text
中,它将无法工作。示例:
let privacyPolicyText = "Read our [Privacy Policy](https://example.com) here."
Text(privacyPolicyText) // Will not work
使用字符串变量的解决方案
原因是Text
得到了多次启迪。那么我们如何解决这个问题呢?最简单的方法就是:
let privacyPolicyText = "Read our [Privacy Policy](https://example.com) here."
Text(.init(privacyPolicyText))
结果:阅读我们的 Privacy Policy 此处。
使用 LocalizedStringKey 非常简单,例如:
let message = "Hello, www.google.com this is just testing for hyperlinks, check this out our website https://www.apple.in thank you."
Text(LocalizedStringKey(message))
我尝试在中间使用 Link 连接文本,这些是 iOS 15+ 及以下 iOS 15.
if #available(iOS 15, *) {
Text("[Seperate Link 1 ](https://www.android.com/intl/en_in/)")
.font(.caption)
.foregroundColor(Color.green)
// green color is not applied.
Text("[Seperate Link 2 ](https://www.apple.com/in/)")
.font(.caption)
.accentColor(Color.green)
// green is applied.
Text("By authorizing you agree
our ")
.font(.caption)
.foregroundColor(Color.black)
+ Text("[Terms and Conditions](https://www.android.com/intl/en_in/)")
.font(.caption)
.foregroundColor(Color.green) // default blue is applied
+ Text(" and ")
.font(.caption)
.foregroundColor(Color.black)
+ Text("[Privacy Policy](https://www.apple.com/in/)")
.font(.caption)
.foregroundColor(Color.green) // default blue
// cannot use accentColor(Color.green) here
}
else{
// lower iOS versions.
VStack{
Text("By authorizing you agree our ")
.font(.caption)
.foregroundColor(Color.black)
HStack(spacing: 4 ) {
Text("Terms and Conditions")
.font(.caption)
.foregroundColor(Color.green)
.onTapGesture {
let url = URL.init(string: "https://www.android.com/intl/en_in/")
guard let termsAndConditionURL = url, UIApplication.shared.canOpenURL(termsAndConditionURL) else { return }
UIApplication.shared.open(termsAndConditionURL)
}
Text("and")
.font(.caption)
.foregroundColor(Color.black)
Text("Privacy Policy")
.font(.caption)
.foregroundColor(Color.green)
.onTapGesture {
let url = URL.init(string: "https://www.apple.com/in/")
guard let privacyPolicyURL = url, UIApplication.shared.canOpenURL(privacyPolicyURL) else { return }
UIApplication.shared.open(privacyPolicyURL)
}
}
}
}