在SwiftUI中突出显示文本的特定部分

pu3pd22g  于 2023-01-04  发布在  Swift
关注(0)|答案(5)|浏览(168)

你好,我是Swift的新手,我正在使用SwiftUI进行我的项目,我在其中下载了一些天气数据,并将其显示在ContentView()中。
我想突出文本的某些部分,如果它包含一些特定的话,但我不知道如何开始。
在ContentView()中,我尝试设置一个函数来接收从Web下载的字符串并返回一个字符串。我认为这是错误的,因为SwiftUI根本没有对文本应用修饰符。
例如,在我的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
  }

}
l5tcr1uw

l5tcr1uw1#

如果这只需要简单的字样式,那么这里是可能的解决方案。
使用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)
}
mkshixfv

mkshixfv2#

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
}
2w2cym1i

2w2cym1i3#

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

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())
cl25kdpy

cl25kdpy4#

如果您的目标是iOS 15/macOS 12及更高版本,则可以使用AttributedString。例如:

private struct HighlightedText: View {
    let text: String
    let highlighted: String

    var body: some View {
        Text(attributedString)
    }

    private var attributedString: AttributedString {
        var attributedString = AttributedString(text)

        if let range = attributedString.range(of: highlighted)) {
            attributedString[range].backgroundColor = .yellow
        }

        return attributedString
    }
}

如果希望匹配不区分大小写,可以替换以下行

if let range = attributedString.range(of: highlighted)

if let range = AttributedString(text.lowercased()).range(of: highlighted.lowercased())
k4aesqcs

k4aesqcs5#

@Asperi的答案很好用,下面是一个修改过的变体,它通过单词数组进行搜索:

func highlightedText(str: String, searched: [String]) -> Text {
    
    guard !str.isEmpty && !searched.isEmpty else { return Text(str) }
    
    var result: Text!
    let parts = str.components(separatedBy: " ")
    
    for part_index in parts.indices {
        result = (result == nil ? Text("") : result + Text(" "))
        if searched.contains(parts[part_index].trimmingCharacters(in: .punctuationCharacters)) {
            result = result + Text(parts[part_index])
                .bold()
                .foregroundColor(.red)
        }
        else {
            result = result + Text(parts[part_index])
        }
    }
    
    return result ?? Text(str)
}

用法示例:

let str: String = "There is a thunderstorm in the area. Added some testing long text to demo that wrapping works correctly!"
        let searched: [String] = ["thunderstorm", "wrapping"]
        
        highlightedText(str: str, searched: searched)
            .padding()
            .background(.yellow)

相关问题