通常,添加两个Text视图将产生一个Text视图,并保留每个Text视图的属性。例如:
Text(“Hello ”) + Text(“world!”).foregroundColor(.blue)
这应该产生Hello world!
,其中world!
为蓝色。现在,如果我想world!
可以轻按并充当按钮,该怎么办?嗯,从逻辑上讲,这样做是有道理的:
Text(“Hello ”) + Button(action: {}) { Text(“world!”).foregroundColor(.blue) }
但是,上面的代码无法编译。是否可以如上所述创建带有可点击部分的文本视图?我的用法cas用于带有@
提及或#
主题标签的推文,您可以在其中提及主题或主题标签,以显示详细视图。
编辑:之所以不适合在HStack中使用文本视图和按钮,是因为这是在返回tweet内容的文本视图的函数内:
func styledText(text: String) -> Text {
var output = Text("")
let components = text.tokenize("@#. ")
for component in components {
if component.rangeOfCharacter(from: CharacterSet(charactersIn: "@#")) != nil {
output = output + Text(component).foregroundColor(.accentColor)
} else {
output = output + Text(component)
}
}
return output
}
String.tokenize
如下:
extension String {
func tokenize(_ delimiters: String) -> [String] {
var output = [String]()
var buffer = ""
for char in self {
if delimiters.contains(char) {
output.append(buffer)
buffer = String(char)
} else {
buffer += String(char)
}
}
output.append(buffer)
return output
}
}
编辑2:如果有帮助,我正在尝试为此创建一个SwiftUI版本:https://github.com/optonaut/ActiveLabel.swift。
答案 0 :(得分:2)
您可以扩展AnyView以获得所需的内容。如果您非常擅长编程,则可以为您的目标引入更复杂的自动布局。
extension AnyView{
static func + (left: AnyView, right: AnyView) -> AnyView{
return AnyView(HStack{left.fixedSize(horizontal: true, vertical: false)
right.fixedSize(horizontal: true, vertical: false)})
}
}
func styledText(text: String) -> AnyView {
var output = AnyView(Text(""))
let components = text.tokenize("@#. ")
for component in components {
if component.rangeOfCharacter(from: CharacterSet(charactersIn: "@#")) != nil {
output = output + AnyView(Text(component).foregroundColor(.accentColor).onTapGesture {
print(component)
})
} else {
output = output + AnyView(Text(component))
}
}
return output
}
答案 1 :(得分:1)
我不确定是要使用还是要明确使用+,但是您可以达到此目标
HStack {
Text("Hello ")
Button(action: {
// do something
print("tapped")
}, label: {
Text("world!").foregroundColor(.blue)
})
}
答案 2 :(得分:1)
这是另一种解决方案,但这仅对链接类型样式真正有用。换句话说,如果需要,我认为没有一个简单的解决方案可以执行任何自定义操作。
我的解决方案建议创建一个可以显示属性字符串的 UIViewRepresentable
:
struct AttributedText: UIViewRepresentable {
var attributedString: NSAttributedString
func makeUIView(context: Context) -> UITextView {
let textView = UITextView()
textView.attributedText = self.attributedString
return textView
}
func updateUIView(_ uiView: UITextView, context: Context) {}
}
然后你可以像这样创建一个属性字符串:
var attributedString: NSAttributedString = {
let attrString = NSMutableAttributedString(string: "Hello, ")
let blueWorld = NSMutableAttributedString(string: "world!")
let attributes: [NSAttributedString.Key : Any ] = [
.link: NSURL(string: "https://twitter.com")!
]
let fullRange = NSRange(location: 0, length: blueWorld.length)
blueWorld.setAttributes(attributes, range: fullRange)
attrString.append(blueWorld)
return attrString
}()
或者使用任何好的库,直到苹果有更好的选择。这使您可以简单地显示文本,因为它是常规的 Text
:
struct MyText {
var body: some View {
AttributedText(attributedString: myCustomAttributedString)
}
}
当您只对链接感兴趣并且可以接受链接的默认显示时,此解决方案具有潜力(据我所知,您无法更改此设置)。
答案 3 :(得分:0)
您不能在此处使用+
,因为.foregroundColor
修饰符会产生some View
,但不会产生Text
实际上,您可以使用几乎相同的内容:
var body: some View {
HStack {
Text("Hello")
Text("world!").foregroundColor(.blue).onTapGesture {
print("world got tapped")
}
}
}