如何在SwiftUI中使用AttributedString。没有可用于在文本中使用AttributedString的API
rpppsulh1#
iOS 15和Swift 5.5Text现在支持markdown,您还可以创建自定义属性:
Text
您甚至可以远程获取定义的属性,例如:
iOS 13和14你可以用一个简单的+操作符将多个Text对象组合在一起,这样就可以处理一些属性:
+
每一个都可以有多个特定的修饰符
由于Text不直接支持UILabel(直到iOS 15),您可以将UILabel带到那里,并根据自己的喜好进行修改:
UILabel
struct UIKLabel: UIViewRepresentable { typealias TheUIView = UILabel fileprivate var configuration = { (view: TheUIView) in } func makeUIView(context: UIViewRepresentableContext<Self>) -> TheUIView { TheUIView() } func updateUIView(_ uiView: TheUIView, context: UIViewRepresentableContext<Self>) { configuration(uiView) } }
var body: some View { UIKLabel { $0.attributedText = NSAttributedString(string: "HelloWorld") } }
s2j5cfk02#
attributed string的概念是 * 字符串与属性 *。在SwiftUI中,此概念通过Text属性修饰符和+运算符实现。如以下示例所示:
attributed string
Group { Text("Bold") .fontWeight(.bold) + Text("Underlined") .underline() + Text("Color") .foregroundColor(Color.red) }
ar5n3qh53#
我们终于得到了AttributedString!它真的很容易使用。
AttributedString
struct ContentView: View { var body: some View { VStack(spacing: 40) { /// Note: You can replace `$0` with `string in string` VStack { Text("Regular") Text("Italics") { $0.font = Font.system(size: 17).italic() } Text("Bold") { $0.font = Font.system(size: 17).bold() } Text("Strikethrough") { $0.strikethroughStyle = Text.LineStyle(pattern: .solid, color: .red) } Text("Code") { $0.font = Font.system(size: 17, design: .monospaced) } Text("Foreground Color") { $0.foregroundColor = Color.purple } Text("Background Color") { $0.backgroundColor = Color.yellow } Text("Underline") { $0.underlineColor = Color.green } } VStack { Text("Kern") { $0.kern = CGFloat(10) } Text("Tracking") { $0.tracking = CGFloat(10) } } VStack { Text("Baseline Offset") { $0.baselineOffset = CGFloat(10) } Text("Link") { $0.link = URL(string: "https://apple.com") } } } } } /// extension to make applying AttributedString even easier extension Text { init(_ string: String, configure: ((inout AttributedString) -> Void)) { var attributedString = AttributedString(string) /// create an `AttributedString` configure(&attributedString) /// configure using the closure self.init(attributedString) /// initialize a `Text` } }
若要将属性应用于特定范围,请使用range(of:options:locale:)方法。
range(of:options:locale:)
struct ContentView: View { var body: some View { Text("Some Attributed String") { string in string.foregroundColor = .blue if let range = string.range(of: "Attributed") { /// here! string[range].foregroundColor = .red } } } }
更多细节请看我的article。另外,你可以use Markdown!
ocebsuys4#
有很多答案都使用UILabel或UITextView。我很好奇是否有可能创建一个不依赖于任何UIKit功能的原生SwiftUI实现。这代表了一个满足我当前需求的实现。它距离NSAttributedString规范的完整实现还很远。但对于最基本的需求来说,它绝对足够好了。接受HTML字符串的NSAttributedString的构造函数是我创建的一个自定义类别,非常容易实现。如果有人想运行它并创建一个更健壮和完整的组件,你会成为我的英雄可惜我没时间做这个项目。
UITextView
NSAttributedString
// // AttributedText.swift // import SwiftUI struct AttributedTextBlock { let content: String let font: Font? let color: Color? } struct AttributedText: View { var attributedText: NSAttributedString? private var descriptions: [AttributedTextBlock] = [] init(_ attributedText: NSAttributedString?) { self.attributedText = attributedText self.extractDescriptions() } init(stringKey: String) { self.init(NSAttributedString(htmlString: NSLocalizedString(stringKey, comment: ""))) } init(htmlString: String) { self.init(NSAttributedString(htmlString: htmlString)) } private mutating func extractDescriptions() { if let text = attributedText { text.enumerateAttributes(in: NSMakeRange(0, text.length), options: [], using: { (attribute, range, stop) in let substring = (text.string as NSString).substring(with: range) let font = (attribute[.font] as? UIFont).map { Font.custom($0.fontName, size: $0.pointSize) } let color = (attribute[.foregroundColor] as? UIColor).map { Color($0) } descriptions.append(AttributedTextBlock(content: substring, font: font, color: color)) }) } } var body: some View { descriptions.map { description in Text(description.content) .font(description.font) .foregroundColor(description.color) }.reduce(Text("")) { (result, text) in result + text } } } struct AttributedText_Previews: PreviewProvider { static var previews: some View { AttributedText(htmlString: "Hello! <b>World</b>") } }
zzlelutf5#
如果希望使用NSAttributedString实现动态高度文本,可以使用以下命令:
struct TextWithAttributedString: View { var attributedText: NSAttributedString @State private var height: CGFloat = .zero var body: some View { InternalTextView(attributedText: attributedText, dynamicHeight: $height) .frame(minHeight: height) } struct InternalTextView: UIViewRepresentable { var attributedText: NSAttributedString @Binding var dynamicHeight: CGFloat func makeUIView(context: Context) -> UITextView { let textView = UITextView() textView.textAlignment = .justified textView.isScrollEnabled = false textView.isUserInteractionEnabled = false textView.showsVerticalScrollIndicator = false textView.showsHorizontalScrollIndicator = false textView.allowsEditingTextAttributes = false textView.backgroundColor = .clear textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) textView.setContentCompressionResistancePriority(.defaultLow, for: .vertical) return textView } func updateUIView(_ uiView: UITextView, context: Context) { uiView.attributedText = attributedText DispatchQueue.main.async { dynamicHeight = uiView.sizeThatFits(CGSize(width: uiView.bounds.width, height: CGFloat.greatestFiniteMagnitude)).height } } } }
VStack { TextWithAttributedString(attributedText: viewModel.description) .padding([.leading, .trailing], self.horizontalPadding) .layoutPriority(1) .background(Color.clear) } .transition(.opacity) .animation(.linear)
svmlkihl6#
为了只为iOS 14添加一种不同的风格,这对我很有效:
struct ItalicTextView: View { let text: String let italicText: String var body: some View { let array = text.components(separatedBy: italicText) array.reduce(Text(""), { if $1 == array.last { return $0 + Text($1) } return $0 + Text($1) + Text(italicText).italic() }) } }
用法:
var body: some View { HStack(alignment: .center, spacing: 0) { ItalicTextView(text: notification.description, italicText: "example") .multilineTextAlignment(.leading) .fixedSize(horizontal: false, vertical: true) .padding(.vertical, 16) .padding(.horizontal, 8) } }
}
hpcdzsge7#
1.适用于MacOS1.比SwiftUI的Text(someInstanceOf_AttributedString)快得多1.点击或选择文本时无需重置字体属性即可选择文本
Text(someInstanceOf_AttributedString)
import SwiftUI import Cocoa @available(OSX 11.0, *) public struct AttributedText: NSViewRepresentable { private let text: NSAttributedString public init(attributedString: NSAttributedString) { text = attributedString } public func makeNSView(context: Context) -> NSTextField { let textField = NSTextField(labelWithAttributedString: text) textField.isSelectable = true textField.allowsEditingTextAttributes = true // Fix of clear of styles on click textField.preferredMaxLayoutWidth = textField.frame.width return textField } public func updateNSView(_ nsView: NSTextField, context: Context) { nsView.attributedStringValue = text } }
7条答案
按热度按时间rpppsulh1#
iOS 15和Swift 5.5
Text
现在支持markdown,您还可以创建自定义属性:您甚至可以远程获取定义的属性,例如:
iOS 13和14
你可以用一个简单的
+
操作符将多个Text
对象组合在一起,这样就可以处理一些属性:每一个都可以有多个特定的修饰符
完全支持的回退!
由于
Text
不直接支持UILabel
(直到iOS 15),您可以将UILabel
带到那里,并根据自己的喜好进行修改:实施:
用法:
s2j5cfk02#
attributed string
的概念是 * 字符串与属性 *。在SwiftUI中,此概念通过Text
属性修饰符和+
运算符实现。如以下示例所示:ar5n3qh53#
iOS 15操作系统
我们终于得到了
AttributedString
!它真的很容易使用。若要将属性应用于特定范围,请使用
range(of:options:locale:)
方法。更多细节请看我的article。另外,你可以use Markdown!
ocebsuys4#
有很多答案都使用
UILabel
或UITextView
。我很好奇是否有可能创建一个不依赖于任何UIKit功能的原生SwiftUI实现。这代表了一个满足我当前需求的实现。它距离NSAttributedString
规范的完整实现还很远。但对于最基本的需求来说,它绝对足够好了。接受HTML字符串的NSAttributedString
的构造函数是我创建的一个自定义类别,非常容易实现。如果有人想运行它并创建一个更健壮和完整的组件,你会成为我的英雄可惜我没时间做这个项目。zzlelutf5#
如果希望使用NSAttributedString实现动态高度文本,可以使用以下命令:
实施:
用法:
svmlkihl6#
为了只为iOS 14添加一种不同的风格,这对我很有效:
用法:
}
hpcdzsge7#
1.适用于MacOS
1.比SwiftUI的
Text(someInstanceOf_AttributedString)
快得多1.点击或选择文本时无需重置字体属性即可选择文本