【问题标题】:Higlight speech utterance in SwiftUI在 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)
    }
}

【问题讨论】:

    标签: swift swiftui avfoundation


    【解决方案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(),但没有帮助。
    • 是的——这个答案详细说明了一个系统:stackoverflow.com/questions/58469001/…
    猜你喜欢
    • 2020-04-16
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多