完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
S7r1n9y
Engineer
このシリーズの記事一覧
- 1. 完全に理解する Storyboard & UIKit (Day 1): 基礎概念と歴史
- 2. 完全に理解する Storyboard & UIKit (Day 2): XcodeでのStoryboardの基本操作
- 3. 完全に理解する Storyboard & UIKit (Day 3): UIViewControllerのライフサイクル
- 4. 完全に理解する Storyboard & UIKit (Day 4): Auto Layoutの基本原理
- 5. 完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
- 6. 完全に理解する Storyboard & UIKit (Day 6): UIStackViewを使った効率的なレイアウト設計
- 7. 完全に理解する Storyboard & UIKit (Day 7): Size Classesによるレスポンシブデザイン
- 8. 完全に理解する Storyboard & UIKit (Day 8): Segueによる画面遷移とデータ渡し
- 9. 完全に理解する Storyboard & UIKit (Day 9): Navigation Controllerの活用
- 10. 完全に理解する Storyboard & UIKit (Day 10): Tab Bar Controllerの活用
- 11. 完全に理解する Storyboard & UIKit (Day 11): 基本的なUI部品(UILabel, UIButton, UITextField)
- 12. 完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
- 13. 完全に理解する Storyboard & UIKit (Day 13): UIImageViewと画像リソース管理
- 14. 完全に理解する Storyboard & UIKit (Day 14): UIScrollViewとコンテンツのスクロール
- 15. 完全に理解する Storyboard & UIKit (Day 15): UITableViewの実装基礎
- 16. 完全に理解する Storyboard & UIKit (Day 16): UITableViewのカスタムセル作成
- 17. 完全に理解する Storyboard & UIKit (Day 17): UICollectionViewの実装基礎
- 18. 完全に理解する Storyboard & UIKit (Day 18): UICollectionViewのカスタムレイアウト
- 19. 完全に理解する Storyboard & UIKit (Day 19): Custom Viewの作成とStoryboardでの利用(@IBDesignable, @IBInspectable)
- 20. 完全に理解する Storyboard & UIKit (Day 20): アニメーションの実装(UIView Animation)
- 21. 完全に理解する Storyboard & UIKit (Day 21): Gesture Recognizerによるタッチ処理
- 22. 完全に理解する Storyboard & UIKit (Day 22): UIAlertControllerによるアラートとアクションシート
- 23. 完全に理解する Storyboard & UIKit (Day 23): UIDatePickerやUIPickerViewの実装
- 24. 完全に理解する Storyboard & UIKit (Day 24): Storyboard Referenceを用いたStoryboard分割
- 25. 完全に理解する Storyboard & UIKit (Day 25): XIBとStoryboardの使い分け・併用
- 26. 完全に理解する Storyboard & UIKit (Day 26): UIAppearanceによるアプリ全体の色・スタイル管理
- 27. 完全に理解する Storyboard & UIKit (Day 27): ダークモード対応とアセットカタログ
- 28. 完全に理解する Storyboard & UIKit (Day 28): Accessibility(VoiceOver対応など)のUI設計
- 29. 完全に理解する Storyboard & UIKit (Day 29): UIKitからSwiftUIへの移行 / UIKitでのSwiftUI利用
- 30. 完全に理解する Storyboard & UIKit (Day 30): 実践:1つのアプリをStoryboardとUIKitで完成させる
Sponsored
完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
Day 11では1行の入力(UITextField)を学びましたが、長文のメモやメッセージを入力させたい場合は UITextView を使います。
また、文字入力を伴うUIにおいて必ず直面する「キーボードの制御(どうやって閉じるか?キーボードの下に隠れてしまうボタンをどうするか?)」という重要課題についても解説します。
1. UITextView (複数行のテキスト入力・表示)
UITextView は、スクロール可能な複数行のテキストを表示・編集するためのビューです。
主な特徴と設定
- 編集可能(Editable) / 選択可能(Selectable):
EditableをOFFにすれば、単なる長文表示用(UILabelの長文版+スクロール付き)として使えます。
- Placeholderがない:
- 致命的な弱点として、
UITextFieldにある Placeholder(薄いヒント文字)プロパティが標準で存在しません。 - 実現するには、背面にUILabelを配置してコードで表示/非表示を切り替えるなどの工夫が必要です。
- 致命的な弱点として、
- スクロール処理:
- 内部に
UIScrollViewを実装しているため、テキストが枠をはみ出すと自動でスクロールします。
- 内部に
2. キーボードを閉じる処理(実装必須)
iOSでは、一度キーボードが表示されると、開発者が明示的に閉じるコードを書かない限り、キーボードは出っ放し になります。
現在の入力状態(フォーカス)を保持しているビューを First Responder と呼びます。キーボードを閉じる「魔法の呪文」は、「First Responder を辞任させること (resignFirstResponder()) 」、または 「画面全体の編集状態を終了させること (endEditing(true)) 」 です。
実用的な3つのパターンを紹介します。
パターンA: 余白(背景)をタップして閉じる
画面の何もない部分をタップした時にキーボードを閉じる、最も直感的で多用される方法です。
touchesBegan メソッドをオーバーライドします。
swiftclass ViewController: UIViewController { // 画面のどこかがタッチされた時に呼ばれる override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { // self.viewとそのサブビューすべての編集状態を終わらせる self.view.endEditing(true) } }
パターンB: キーボードの「完了(Return/Done)」ボタンで閉じる
UITextField で文字入力を終え、右下のボタンを押した時に閉じます。(UITextFieldDelegate プロトコルを使用します)
swiftclass ViewController: UIViewController, UITextFieldDelegate { @IBOutlet weak var myTextField: UITextField! override func viewDidLoad() { super.viewDidLoad() // デリゲート(アクションの処理の委譲先)を自分自身に設定 myTextField.delegate = self } // Returnキーが押された時に呼ばれるデリゲートメソッド func textFieldShouldReturn(_ textField: UITextField) -> Bool { // キーボードを閉じる textField.resignFirstResponder() return true } }
パターンC: スクロールして閉じる (UIScrollView / UITableView)
Storyboardで ScrollView や TableView を選択し、Attributes Inspector の Keyboard 項目を Dismiss on drag(ドラッグで閉じる)に設定するだけで、コード不要で実現できます。
3. キーボードで画面が隠れる問題の解決
画面下部にあるTextFieldをタップすると、下からせり上がってきたキーボードによって入力欄自身が隠れてしまい、自分が何を打っているか分からなくなる問題があります。
これを解決するには、キーボードの出現・消失を知らせる Notification(通知) を受け取り、画面(View)全体を上にスライドさせる処理を書きます。
swiftoverride func viewDidLoad() { super.viewDidLoad() // キーボードが現れる通知を監視 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) // キーボードが隠れる通知を監視 NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) } @objc func keyboardWillShow(notification: NSNotification) { if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { // キーボードの高さの分だけ、画面全体を上にずらす(被らないように調整) if self.view.frame.origin.y == 0 { self.view.frame.origin.y -= keyboardSize.height } } } @objc func keyboardWillHide(notification: NSNotification) { // 画面を元の位置に戻す if self.view.frame.origin.y != 0 { self.view.frame.origin.y = 0 } }
※ 実際には、対象のTextFieldが既にキーボードより上にある場合は動かさない、Auto Layoutのパラメーター(Bottom Constraint)の方を書き換える、といったより詳細な制御が推奨されます。(最近は IQKeyboardManager 等のライブラリを入れて自動解決させるプロジェクトも多いです)
📝 今日のまとめ
- UITextView: 複数行長文用。実はスクロールビューの一種。
- キーボードを閉じるには:
self.view.endEditing(true)かresignFirstResponder()を呼ぶ。 - キーボードが被る問題:
NotificationCenterで高さを取得し、画面位置や制約をアニメーション付きでずらして対応する。
ユーザー入力についての鬼門を突破しました。次は視覚的な表現に欠かせない「画像」の取り扱いです。
明日の Day 13 では、UIImageView と、画像リソースを管理する Asset Catalog について学びます。
このシリーズの記事一覧
- 1. 完全に理解する Storyboard & UIKit (Day 1): 基礎概念と歴史
- 2. 完全に理解する Storyboard & UIKit (Day 2): XcodeでのStoryboardの基本操作
- 3. 完全に理解する Storyboard & UIKit (Day 3): UIViewControllerのライフサイクル
- 4. 完全に理解する Storyboard & UIKit (Day 4): Auto Layoutの基本原理
- 5. 完全に理解する Storyboard & UIKit (Day 5): Auto Layoutの複雑な制約の解決
- 6. 完全に理解する Storyboard & UIKit (Day 6): UIStackViewを使った効率的なレイアウト設計
- 7. 完全に理解する Storyboard & UIKit (Day 7): Size Classesによるレスポンシブデザイン
- 8. 完全に理解する Storyboard & UIKit (Day 8): Segueによる画面遷移とデータ渡し
- 9. 完全に理解する Storyboard & UIKit (Day 9): Navigation Controllerの活用
- 10. 完全に理解する Storyboard & UIKit (Day 10): Tab Bar Controllerの活用
- 11. 完全に理解する Storyboard & UIKit (Day 11): 基本的なUI部品(UILabel, UIButton, UITextField)
- 12. 完全に理解する Storyboard & UIKit (Day 12): UITextViewとキーボードハンドリング
- 13. 完全に理解する Storyboard & UIKit (Day 13): UIImageViewと画像リソース管理
- 14. 完全に理解する Storyboard & UIKit (Day 14): UIScrollViewとコンテンツのスクロール
- 15. 完全に理解する Storyboard & UIKit (Day 15): UITableViewの実装基礎
- 16. 完全に理解する Storyboard & UIKit (Day 16): UITableViewのカスタムセル作成
- 17. 完全に理解する Storyboard & UIKit (Day 17): UICollectionViewの実装基礎
- 18. 完全に理解する Storyboard & UIKit (Day 18): UICollectionViewのカスタムレイアウト
- 19. 完全に理解する Storyboard & UIKit (Day 19): Custom Viewの作成とStoryboardでの利用(@IBDesignable, @IBInspectable)
- 20. 完全に理解する Storyboard & UIKit (Day 20): アニメーションの実装(UIView Animation)
- 21. 完全に理解する Storyboard & UIKit (Day 21): Gesture Recognizerによるタッチ処理
- 22. 完全に理解する Storyboard & UIKit (Day 22): UIAlertControllerによるアラートとアクションシート
- 23. 完全に理解する Storyboard & UIKit (Day 23): UIDatePickerやUIPickerViewの実装
- 24. 完全に理解する Storyboard & UIKit (Day 24): Storyboard Referenceを用いたStoryboard分割
- 25. 完全に理解する Storyboard & UIKit (Day 25): XIBとStoryboardの使い分け・併用
- 26. 完全に理解する Storyboard & UIKit (Day 26): UIAppearanceによるアプリ全体の色・スタイル管理
- 27. 完全に理解する Storyboard & UIKit (Day 27): ダークモード対応とアセットカタログ
- 28. 完全に理解する Storyboard & UIKit (Day 28): Accessibility(VoiceOver対応など)のUI設計
- 29. 完全に理解する Storyboard & UIKit (Day 29): UIKitからSwiftUIへの移行 / UIKitでのSwiftUI利用
- 30. 完全に理解する Storyboard & UIKit (Day 30): 実践:1つのアプリをStoryboardとUIKitで完成させる