UITextViewをUIViewRepresentableでラッピングして以下の様に使用しています。また文字をハイライトできる様にboundingRectで文字の範囲を取得してUIViewにaddしています。
SwiftUI
1 struct CustomTextView: UIViewRepresentable { 2 3 @ObservedObject var tmpTextVM: TmpTextViewModel 4 5 func makeUIView(context: UIViewRepresentableContext<CustomTextView>) -> UITextView { 6 let textView = UITextView() 7 textView.backgroundColor = UIColor.clear 8 textView.isScrollEnabled = false 9 textView.text = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 10 textView.font = UIFont(name: "ArialMT", size: 20) 11 textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) 12 return textView 13 } 14 15 func updateUIView(_ uiView: UITextView, context: Context) { 16 17 uiView.textColor = tmpTextVM.color 18 19 20 let range = (uiView.text as NSString).range(of: uiView.text) 21 var rect = uiView.layoutManager.boundingRect(forGlyphRange: range, in: uiView.textContainer) 22 23 rect.size.width += 25 24 rect.size.height += 10 25 rect.origin.x += uiView.textContainerInset.left - 10 26 rect.origin.y += uiView.textContainerInset.top - 5 27 28 uiView.viewWithTag(300)?.removeFromSuperview() 29 30 let view = UIView() 31 32 view.backgroundColor = UIColor.blue 33 34 view.layer.cornerRadius = 10 35 view.frame = rect 36 view.tag = 300 37 38 uiView.addSubview(view) 39 uiView.sendSubviewToBack(view) 40 41 } 42} 43
これを使用する際には以下の様にします。
SwiftUI
1struct TmpView7View: View { 2 3 @ObservedObject var tmpTextVM: TmpTextViewModel 4 5 var body: some View { 6 VStack { 7 8 Button(action: { 9 tmpTextVM.changeColor(UIColor.red) 10 }){ 11 Image(systemName:"eyedropper.full") 12 } 13 14 CustomTextView(tmpTextVM: tmpTextVM) 15 .frame(width:300, height: 300, alignment: .topLeading) 16 .border(Color.red, width: 1) 17 } 18 } 19}
ただこれだと文字の高さが1行分だけしか取得できていない様でこの様になります。
上のボタンでを押すとObservedObjectの値が更新されて再度updateUIViewが動き、そうすると以下の様に全ての文字がハイライトされます。
最初から正しい文字の高さを取得するにはどうすれば良いでしょうか?
最初にmakeUIViewが呼ばれたた後にもupdateUIViewは呼ばれていますがその際には正しい高さが取得できなくてその次のupdateUIViewで正しく高さが取得できる様です。
因みにあまり関係ありませんがObservedObjectのクラスは以下の様になっています。これでほぼコードの全てなので実際に動きます。
SwiftUI
1class TmpTextViewModel: ObservableObject { 2 3 @Published private var tmpTextModel: TmpTextModel = TmpTextModel() 4 5 var color: UIColor {tmpTextModel.color} 6 7 func changeColor(_ color: UIColor) { 8 tmpTextModel.color = color 9 } 10 11}
SwiftUI
1struct TmpTextModel { 2 3 var color:UIColor = UIColor.purple 4 5}
あなたの回答
tips
プレビュー