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

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

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

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

Q&A

解決済

1回答

1346閲覧

【Swift】UITextViewの高さを入力内容に合わせて変える方法

konakizzi_mk

総合スコア21

Swift

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

0グッド

0クリップ

投稿2022/06/17 03:05

編集2022/06/20 01:23

課題

こちらを参考にし、UITextViewの高さを入力内容に合わせて変えることはできたのですが、ボタン押下後に入力していたtextを空にした場合、入力していた文字の高さが残ってしまいます。
ボタン押下後はデフォルトのtextViewの高さに戻すにはどうしたら良いでしょうか?

Swift

1 2import UIKit 3 4class ViewController:UIViewController { 5 6 @IBOutlet weak var testView: UITextView! 7 @IBOutlet weak var textViewHeight: NSLayoutConstraint! 8 @IBOutlet weak var viewHeight: NSLayoutConstraint! 9 10 var currentTextViewHeight: CGFloat = 80 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 // Do any additional setup after loading the view. 14 self.testView.delegate = self 15 } 16 @IBAction func tapButton(_ sender: Any) { 17 testView.text = "" 18 textViewHeight.constant = 80 19 } 20} 21 22extension ViewController: UITextViewDelegate { 23 func textViewDidChange(_ textView: UITextView) { 24 let contentHeight = self.testView.contentSize.height 25 26 if 80.0 <= contentHeight && contentHeight <= 100.0 { 27 28 self.testView.translatesAutoresizingMaskIntoConstraints = true 29 self.testView.sizeToFit() 30 self.testView.isScrollEnabled = false 31 let resizedHeight = self.testView.frame.size.height 32 self.textViewHeight.constant = resizedHeight 33 self.testView.frame = CGRect(x: 60, y: 30, width: self.view.frame.width - 120, height: resizedHeight) 34 35 if resizedHeight > currentTextViewHeight { 36 let addingHeight = resizedHeight - currentTextViewHeight 37 self.viewHeight.constant += addingHeight 38 currentTextViewHeight = resizedHeight 39 } else if resizedHeight < currentTextViewHeight { 40 let subtractingHeight = currentTextViewHeight - resizedHeight 41 self.viewHeight.constant -= subtractingHeight 42 currentTextViewHeight = resizedHeight 43 } 44 45 } else { 46 47 self.testView.isScrollEnabled = true 48 self.textViewHeight.constant = currentTextViewHeight 49 self.testView.frame = CGRect(x: 60, y: 30, width: self.view.frame.width - 120, height: currentTextViewHeight) 50 51 } 52 53 } 54} 55

ボタンタップのアクション内に textViewHeight.constant = 80を書いたのですが高さが残ったままになってしまうのでデフォルトの高さに戻したいです。。。

デフォルトの高さ入力文字数で高さ可変ボタン押下後
イメージ説明イメージ説明イメージ説明
viewの設定textViewの設定
イメージ説明イメージ説明

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

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

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

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

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

guest

回答1

0

ベストアンサー

textViewDidChange(_:)の中で高さを変えているようですので、
それと同じ処理をしてみたらどうでしょうか。

swift

1 @IBAction func tapButton(_ sender: Any) { 2 testView.text = "" 3// textViewHeight.constant = 80 4 textViewDidChange(self.testView) 5 }

コメントありがとうございます。
追記です。

すみません、StoryboardのConstraintsが再現できなくて、動きがどうなっているのか正しく把握できておりません・・

おそらく今はテキストの高さが80未満になっていて、
textViewDidChange(_:)メソッドのifのelseに入っているのかなと思っています。

すごく強引ですが、次のような感じはどうでしょうか。
一旦、3行分だけのテキストを設定して、それでサイズを合わせます。
するとifのtrueの方の処理がされると思います。
それからテキストを空にしてサイズを合わせます。
するとifのelseの方の処理がされると思います。
結果的に3行分の高さになると思うのですがどうでしょうか。

swift

1testView.text = "1\n2\n3" 2textViewDidChange(self.testView) 3testView.text = "" 4textViewDidChange(self.testView)

本当は、高さの初期値を確認しておいて、
その初期値を設定する処理をした方が良いのかなと思います。
(textViewDidChange(_:)メソッドのifのtrueの処理と同等のことをする感じです)
(再現できていないのでわからないのですが、高さの初期値は80なのでしょうか)

swift

1self.testView.translatesAutoresizingMaskIntoConstraints = true 2self.testView.sizeToFit() 3self.testView.isScrollEnabled = false 4self.textViewHeight.constant = 80 // ***** 高さの初期値 5self.testView.frame = CGRect(x: 60, y: 30, width: self.view.frame.width - 120, height: 80) // ***** 高さの初期値 6self.viewHeight.constant = 80 // ***** 高さの初期値 7currentTextViewHeight = 80 // ***** 高さの初期値

コメントありがとうございます。
2つ目の追記です。

スクロールが発生する高さになった場合、デフォルトの高さに戻すにはどうしたら良いでしょうか。。。?

多分、テキストビューの高さは66.5で、それのコンテナーとなるビューの高さは80ということだと思いますので、
次のような感じはどうでしょうか。

swift

1@IBAction func tapButton(_ sender: Any) { 2 testView.text = "" 3// textViewHeight.constant = 80 4 self.testView.translatesAutoresizingMaskIntoConstraints = true 5 self.testView.sizeToFit() 6 self.testView.isScrollEnabled = false 7 self.textViewHeight.constant = 66.5 8 self.testView.frame = CGRect(x: 60, y: 30, width: self.view.frame.width - 120, height: 66.5) 9 self.viewHeight.constant = 80 10 currentTextViewHeight = 66.5 11}

textViewDidChange(_:)メソッドの中は、

if 66.5 <= contentHeight && contentHeight <= 100.0 { 処理の中身は変えず } で試したところ

の状態で確認してみてください。


コメントありがとうございます。
3つ目の追記です。

しかし、ボタン押下後はボタン押下直前のcontentHeightの高さが残っているようでif trueに入ってしまいます・・・

ボタン押下直前のcontentHeightの高さというより、
空の文字列にして、self.testView.sizeToFit()したことにより1行分の高さ(33程度?)になってしまっているのかもしれません。
すみません、すぐに良い方法が思いつかないので、、
やっぱり次のようにしてみたらどうでしょうか。

swift

1 @IBAction func tapButton(_ sender: Any) { 2 testView.text = "\n\n" 3 textViewDidChange(self.testView) 4 testView.text = "" 5 textViewDidChange(self.testView) 6 }

投稿2022/06/19 02:08

編集2022/06/20 11:19
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

konakizzi_mk

2022/06/19 12:07

ありがとうございます! 試してみたら、ボタン押下後1行分の高さになってしまいました。。。 textViewDidChange内の条件が足りないでしょうか。。。?
退会済みユーザー

退会済みユーザー

2022/06/19 12:46

コメントありがとうございます。 > 試してみたら、ボタン押下後1行分の高さになってしまいました。。。 > textViewDidChange内の条件が足りないでしょうか。。。? すみません、あまりConstraintに詳しくないものですから・・ 質問欄に「デフォルトの高さ」で3行分の高さがあると思いますが、 これを削除していったら1行分の高さになりますでしょうか? 希望する動作は文字がなくても3行分の高さを確保しておくことなのでしょうか?
konakizzi_mk

2022/06/20 00:46

>質問欄に「デフォルトの高さ」で3行分の高さがあると思いますが、 >これを削除していったら1行分の高さになりますでしょうか? 入力文字を削除しても1行分の高さにはならずに、デフォルトの高さ(3行分)までは削除されます。 >希望する動作は文字がなくても3行分の高さを確保しておくことなのでしょうか? はい、仰る通りでございます。入力文字削除後もボタン押下後も3行分の高さを確保したいと思っていますmm
konakizzi_mk

2022/06/20 02:11 編集

コメントありがとうございます! 念の為storyboardのスクショも添付しました! ちなみにtextViewのフォントはSystem 14.0を設定しています。
konakizzi_mk

2022/06/20 03:06

すみません。。。高さの初期値80は間違っていて3行分だけのテキストを設定してみたところ、contentHeightとresizedHeightが66.5となっていたのでcurrentTextViewHeightの初期値を66.5に設定しました。 よって if 66.5 <= contentHeight && contentHeight <= 100.0 { 処理の中身は変えず } で試したところ、やはりボタン押下後に1行分の高さになってしまいました。。。 ちなみに参考にした記事の通りでstoryboardとソースコードを試したところ4行分入力しelseに入ってきたところでボタン押下したところ高さが残ってしまいました。 スクロールが発生する高さになった場合、デフォルトの高さに戻すにはどうしたら良いでしょうか。。。? (何度も質問をしてしまい申し訳ございません)
konakizzi_mk

2022/06/20 06:59 編集

ご丁寧にありがとうございます!段々と理解できてきましたmm 最後になるのですが、今のままだと、ボタン押下後に再度テキスト入力するとif elseの方に入って、入力した高さ(1行分)のtextViewHeightになりif trueの方に入るまで1行でスクロールし続けてしまいます。 ボタン押下後、デフォルトの高さを維持しながらtextViewDidChange(_:)メソッドを使用できたらと思うのですが、ご教示いただけないでしょうか?mm
退会済みユーザー

退会済みユーザー

2022/06/20 07:17

> 最後になるのですが、今のままだと、ボタン押下後に再度テキスト入力するとif elseの方に入って、入力した高さ(1行分)のtextViewHeightになりif trueの方に入るまで1行でスクロールし続けてしまいます。 >> 入力文字を削除しても1行分の高さにはならずに、デフォルトの高さ(3行分)までは削除されます。 これは、4行、3行、2行、1行のように削除していくときは高さは3行分確保されるけれども、 1行、2行、3行、4行のように入力していくと高さが1行分とか2行分になってしまう(3行分が確保されていない)ということでしょうか。
konakizzi_mk

2022/06/20 07:26 編集

詳細が不足しており申し訳ございません。 ビルド後すぐに1行、2行、3行、4行のように入力すると最大値まで高さが増加し、4行、3行、2行、1行のように削除していくとデフォルト(3行分)まで減少するのですが、ボタンタップで空にした後、デフォルトの高さになり(ここまではできました)、再度1行と入力するとif elseの方に入りデフォルト高さから1行分の高さになってしまいます。 よってボタンタップ後もビルド後のような正しい挙動をしてほしいと考えております。
退会済みユーザー

退会済みユーザー

2022/06/20 07:31

すみません、ちゃんと確認したいことを書けていませんでした・・ ボタンは関係なく、textViewDidChange(_:)メソッドだけの動きを確認したかったので、 ビルド後、1行、2行、3行、4行のように入力、 4行、3行、2行、1行のように削除、 それから再度、1行、2行、3行、4行のように入力、 4行、3行、2行、1行のように削除、 を繰り返した場合に、3行分の高さは必ず確保されていますでしょうか。 多分、1行分の高さになってしまうのではないかと思うのですが、 そうすると、textViewDidChange(_:)メソッドの処理があまり適切ではないように思うのですが、 (処理によって初期値とは異なる状態にしてしまっている?) その場合、デバッグしながら何が違うのか調べる必要があると思います・・
konakizzi_mk

2022/06/20 07:46 編集

すみません、質問の意図を理解しました。 行の増加減少を繰り返した場合、現状4行まで増加、2行まで減少(必ず2行分の高さが確保される)となっていました。デフォルトを3行分にしているので減少がおかしそうですした・・・
konakizzi_mk

2022/06/20 10:34 編集

失礼しました、3行分の高さで固定されるようにサイズの調整しましたmm デバックしてみたところ、ボタン押下前の処理では1、2、3行まではelseの方に入り、4行目からif trueの方に入りました。しかし、ボタン押下後のテキスト入力では1行目からif trueの方に入っていることがわかりました。 なぜボタン押下前と後でcontentHeightに違いが生じてしまうのかご教示いただけますと幸いです・・・
退会済みユーザー

退会済みユーザー

2022/06/20 10:52

> しかし、ボタン押下後のテキスト入力では1行目からif trueの方に入っていることがわかりました。 > なぜボタン押下前と後でcontentHeightに違いが生じてしまうのかご教示いただけますと幸いです・・・ self.testView.contentSize.heightが80(66.5?)〜100になっているのでしょうか。 textViewDidChangeの処理内容とtapButtonメソッドの初期化内容は基本的に同じように修正しないといけないのかなと思います。 ちょっと最新のソースがどうなっているのかちゃんと把握できていないかもしれなくて・・想像で書いてしまっています・・
konakizzi_mk

2022/06/20 11:05 編集

はい、仰る通りです。self.testView.contentSize.heightを80〜100で設定しております。初期値も80に戻し、tapButtonの高さも合わせ、3行分固定を実現しました。 しかし、ボタン押下後はボタン押下直前のcontentHeightの高さが残っているようでif trueに入ってしまいます・・・
konakizzi_mk

2022/06/20 11:26

コメントありがとうございます!実現したい挙動にはなりました! 親身に対応くださり誠にありがとうございましたmm
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問