SwiftUI中如何通过Binding布尔值控制自定义UITextView的焦点状态
问题解答
现有代码无法实现你期望的功能——因为当前代码没有监听isFirstResponder的状态变化,也没有触发UITextView获取/失去焦点的逻辑。要实现需求,需要对代码做以下两处修改:
修改点1:在updateUIView中处理焦点切换
在updateUIView方法里添加对isFirstResponder绑定值的判断,根据状态触发UITextView的焦点操作:
func updateUIView(_ uiView: UITextView, context: Context){ DispatchQueue.main.async{ // 处理焦点状态 if self.isFirstResponder != uiView.isFirstResponder { if self.isFirstResponder { uiView.becomeFirstResponder() } else { uiView.resignFirstResponder() } } // 原有高度计算逻辑 if uiView.contentSize.height < maxHeight { self.height = uiView.contentSize.height self.lines = uiView.contentSize.height == 38 ? 0 : (uiView.contentSize.height / 21 * 13 - 38) } uiView.text = self.txt } }
修改点2:在Coordinator中同步焦点状态到绑定值
在Coordinator类中补充两个UITextViewDelegate方法,确保用户手动操作(点击文本框/收起键盘)时,isFirstResponder绑定值能同步更新:
class Coordinator: NSObject, UITextViewDelegate{ var parent: ResizableTF let maxHeight: CGFloat = 150 init(parent1: ResizableTF) { parent = parent1 } func textViewDidBeginEditing(_ textView: UITextView) { parent.isFirstResponder = true // 同步开始编辑状态 if self.parent.txt == "" { textView.text = "" textView.textColor = .black } } func textViewDidEndEditing(_ textView: UITextView) { parent.isFirstResponder = false // 同步结束编辑状态 } func textViewDidChange(_ textView: UITextView) { DispatchQueue.main.async { if textView.contentSize.height < self.maxHeight { self.parent.height = textView.contentSize.height } self.parent.txt = textView.text } } }
修改后的完整代码
import Foundation import SwiftUI struct ResizableTF: UIViewRepresentable { @Binding var txt: String @Binding var height: CGFloat @Binding var lines: CGFloat @Binding var isFirstResponder: Bool let maxHeight: CGFloat = 150 func makeCoordinator() -> Coordinator { return ResizableTF.Coordinator(parent1: self) } func makeUIView(context: Context) -> UITextView { let view = UITextView() view.isEditable = true view.isUserInteractionEnabled = true view.isScrollEnabled = true view.font = .systemFont(ofSize: 18) view.textColor = .gray view.backgroundColor = .clear view.delegate = context.coordinator return view } func updateUIView(_ uiView: UITextView, context: Context){ DispatchQueue.main.async{ // 处理焦点状态同步 if self.isFirstResponder != uiView.isFirstResponder { self.isFirstResponder ? uiView.becomeFirstResponder() : uiView.resignFirstResponder() } // 原有高度与文本同步逻辑 if uiView.contentSize.height < maxHeight { self.height = uiView.contentSize.height self.lines = uiView.contentSize.height == 38 ? 0 : (uiView.contentSize.height / 21 * 13 - 38) } uiView.text = self.txt } } class Coordinator: NSObject, UITextViewDelegate{ var parent: ResizableTF let maxHeight: CGFloat = 150 init(parent1: ResizableTF) { parent = parent1 } func textViewDidBeginEditing(_ textView: UITextView) { parent.isFirstResponder = true if parent.txt.isEmpty { textView.text = "" textView.textColor = .black } } func textViewDidEndEditing(_ textView: UITextView) { parent.isFirstResponder = false } func textViewDidChange(_ textView: UITextView) { DispatchQueue.main.async { if textView.contentSize.height < self.maxHeight { self.parent.height = textView.contentSize.height } self.parent.txt = textView.text } } } }
内容的提问来源于stack exchange,提问作者Cham
相关产品推荐
相关产品推荐

