在 SwiftUI 中突出显示语音话语

Posted

技术标签:

【中文标题】在 SwiftUI 中突出显示语音话语【英文标题】:Higlight speech utterance in SwiftUI 【发布时间】:2021-02-10 15:58:26 【问题描述】:

我没有成功在 SwiftUI 中突出显示文本。我只在 UIKit 中找到了它的例子。 在 UIKit 中它应该是 var label: UILabel!,但在 SwiftUI 中标签必须是 String。我试图在函数内部将NSMutableAttributedString 转换为String 格式,但它在抱怨。 如何使用String 格式解决它,以便它也可以在 SwiftUI 中使用?

import AVFoundation

class Speaker: NSObject 
    let synth = AVSpeechSynthesizer()
    var label: String // <- problem
    

    override init() 
        super.init()
        synth.delegate = self
    

    func speak(_ string: String) 
        let utterance = AVSpeechUtterance(string: string)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
        utterance.rate = 0.4
        synth.speak(utterance)
    
    
    // Functions to highlight text
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) 
        let mutableAttributedString = NSMutableAttributedString(string: utterance.speechString)
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: characterRange)
        label.attributedText = mutableAttributedString
    

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) 
        label.attributedText = NSAttributedString(string: utterance.speechString)
    

【问题讨论】:

【参考方案1】:

我建议您将UILabel 包装在UIViewRepresentable 中,以便您可以像以前一样继续使用属性字符串:


struct ContentView : View 
    @ObservedObject var speaker = Speaker()
    
    var body: some View 
        VStack 
            LabelRepresented(text: speaker.label)
        .onAppear 
            speaker.speak("Hi. This is a test.")
        
    


struct LabelRepresented: UIViewRepresentable 
    var text : NSAttributedString?
    
    func makeUIView(context: Context) -> UILabel 
        return UILabel()
    
    
    func updateUIView(_ uiView: UILabel, context: Context) 
        uiView.attributedText = text
    


class Speaker: NSObject, ObservableObject, AVSpeechSynthesizerDelegate 
    let synth = AVSpeechSynthesizer()
    @Published var label: NSAttributedString? // <- change to AttributedString
    

    override init() 
        super.init()
        synth.delegate = self
    

    func speak(_ string: String) 
        let utterance = AVSpeechUtterance(string: string)
        utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
        utterance.rate = 0.4
        synth.speak(utterance)
    
    
    // Functions to highlight text
    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, willSpeakRangeOfSpeechString characterRange: NSRange, utterance: AVSpeechUtterance) 
        let mutableAttributedString = NSMutableAttributedString(string: utterance.speechString)
        mutableAttributedString.addAttribute(.foregroundColor, value: UIColor.red, range: characterRange)
        label = mutableAttributedString
    

    func speechSynthesizer(_ synthesizer: AVSpeechSynthesizer, didFinish utterance: AVSpeechUtterance) 
        label = NSAttributedString(string: utterance.speechString)
    


我将label 更改为NSAttributedString?,并将其设置为ObservableObject 上的@Published 属性——这样,当它发生更改时,视图会立即得到通知。

UIViewRepresentable 创建一个标签,并在其更改时使用属性字符串对其进行更新。

如果您确实想尝试更纯粹的 SwiftUI 方法,这篇博文有一些在 SwiftUI 中使用 NSAttributedString 的好资源(包括我采用的方法):https://swiftui-lab.com/attributed-strings-with-swiftui/

【讨论】:

谢谢!!!如何对齐 UILablel 视图?对于长文本,它会水平扩展超出屏幕范围。我在正文视图中尝试过.padding(),但没有帮助。 是的——这个答案详细说明了一个系统:***.com/questions/58469001/…

以上是关于在 SwiftUI 中突出显示语音话语的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 中关闭按钮突出显示

表单/表格中的 SwiftUI 多个 NavigationLink - 条目保持突出显示

如何在 SwiftUI 中清除列表项上的默认突出显示灰色?

SwiftUI:使用 WkWebView 突出显示具有不同颜色的文本

以编程方式突出显示 SwiftUI 按钮

SwiftUI:是不是存在修饰符来突出显示 Text() 视图的子字符串?