【问题标题】:Highlight a specific part of the text in SwiftUI在 SwiftUI 中突出显示文本的特定部分
【发布时间】:2020-09-18 12:48:38
【问题描述】:

您好,我是 Swift 新手,我在项目中使用 SwiftUI,我下载了一些天气数据并将其显示在 ContentView() 中。

如果文本的某些部分包含某个特定单词,我想突出显示它,但我不知道如何开始。

在 ContentView() 中,我尝试设置一个函数接收从网络下载的字符串并返回一个字符串。我认为这是错误的,因为 SwiftUI 根本没有为 Text 应用修饰符。

例如,在我的 ContentView() 中,我希望雷暴这个词具有 .bold() 修饰符:

struct ContentView: View {
  let testo : String = "There is a thunderstorm in the area"

  var body: some View {
    Text(highlight(str: testo))
  }

  func highlight(str: String) -> String {
    let textToSearch = "thunderstorm"
    var result = ""

    if str.contains(textToSearch) {
      let index = str.startIndex
      result = String( str[index])
    }

    return result
  }

}

【问题讨论】:

标签: swift string search text swiftui


【解决方案1】:

如果只需要简单的文字样式,那么这里是可能的解决方案。

使用 Xcode 11.4 / iOS 13.4 测试

struct ContentView: View {
    let testo : String = "There is a thunderstorm in the area. Added some testing long text to demo that wrapping works correctly!"


    var body: some View {
        hilightedText(str: testo, searched: "thunderstorm")
            .multilineTextAlignment(.leading)
    }

    func hilightedText(str: String, searched: String) -> Text {
        guard !str.isEmpty && !searched.isEmpty else { return Text(str) }

        var result: Text!
        let parts = str.components(separatedBy: searched)
        for i in parts.indices {
            result = (result == nil ? Text(parts[i]) : result + Text(parts[i]))
            if i != parts.count - 1 {
                result = result + Text(searched).bold()
            }
        }
        return result ?? Text(str)
    }
}

注意:下面是以前使用的函数,但正如@Lkabo所评论的那样,它对非常长的字符串有限制

func hilightedText(str: String) -> Text {
    let textToSearch = "thunderstorm"
    var result: Text!

    for word in str.split(separator: " ") {
        var text = Text(word)
        if word == textToSearch {
            text = text.bold()
        }
        result = (result == nil ? text : result + Text(" ") + text)
    }
    return result ?? Text(str)
}

【讨论】:

  • 感谢您的回答,我遇到了一些字符串大于 32k 的问题。不知道该怎么办..有什么想法吗?
  • 要根据你的回答发布一个新问题,我会在这里链接到它..
  • 此解决方案区分大小写,是否有不区分大小写的替代方案?意思是搜索 Foo 或 foo 应该得到相同的结果
【解决方案2】:

iOS 13,Swift 5。这篇中型文章中描述了一个通用的解决方案。使用它,您可以在任何地方突出显示任何文本,唯一的问题是它的长度不能超过 64 个字符,因为它使用按位掩码。

https://medium.com/@marklucking/an-interesting-challenge-with-swiftui-9ebb26e77376

这是文章中的基本代码。

ForEach((0 ..< letter.count), id: \.self) { column in
      Text(letter[column])
        .foregroundColor(colorCode(gate: Int(self.gate), no: column) ? Color.black: Color.red)
        .font(Fonts.futuraCondensedMedium(size: fontSize))

    }

还有这个用来掩盖文字的……

func colorCode(gate:Int, no:Int) -> Bool {

 let bgr = String(gate, radix:2).pad(with: "0", toLength: 16)
 let bcr = String(no, radix:2).pad(with: "0", toLength: 16)
 let binaryColumn = 1 << no - 1

 let value = UInt64(gate) & UInt64(binaryColumn)
 let vr = String(value, radix:2).pad(with: "0", toLength: 16)

 print("bg ",bgr," bc ",bcr,vr)
 return value > 0 ? true:false
}

【讨论】:

    【解决方案3】:

    您可以连接多个文本视图。

    import SwiftUI
    import PlaygroundSupport
    
    struct ContentView: View {
      var body: some View{
        let testo : String = "There is a thunderstorm in the area"
        let stringArray = testo.components(separatedBy: " ")
        let stringToTextView = stringArray.reduce(Text(""), {
          if $1 == "thunderstorm" {
            return $0 + Text($1).bold() + Text(" ")
          } else {
            return $0 + Text($1) + Text(" ")
          }
    
        })
        return stringToTextView
      }
    }
    
    PlaygroundPage.current.setLiveView(ContentView())
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-29
      • 2013-09-16
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多