在 SwiftUI 中突出显示语音
Higlight speech utterance in SwiftUI
我无法在 SwiftUI 中突出显示文本话语。我只在 UIKit 中找到过它的例子。
在 UIKit 中它应该是 var label: UILabel!
,但在 SwiftUI 中标签必须是字符串。我试图在函数内部将 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)
}
}
我建议您将 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/
我无法在 SwiftUI 中突出显示文本话语。我只在 UIKit 中找到过它的例子。
在 UIKit 中它应该是 var label: UILabel!
,但在 SwiftUI 中标签必须是字符串。我试图在函数内部将 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)
}
}
我建议您将 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/