質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

0回答

1009閲覧

【SwiftUI】 UITextViewでboundingRectが上手く動きません・・・

Hayato1201

総合スコア220

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/12/09 13:52

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}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問