LoginSignup
4
3

More than 3 years have passed since last update.

【SwiftUI】キーボードで文字が隠れないようにする制御

Posted at

キーボード処理

TextFieldを選択し、文字を入力するときにキーボードで隠れてしまい入力箇所が見れない場合があります。
キーボードの高さだけビュー全体を上にあげることで解決することが常套手段で、それをSwiftUIでも実装してみたのが今回の話です。
ObservableObjectのクラスで実装を行います。

実装

キーボードの制御を管理するファイルを作ってください。

KeyboardObserver.swift
import SwiftUI
import Combine

class KeyboardObserver: ObservableObject {

  @Published var keyboardHeight: CGFloat = 0.0

  // キーボードの監視開始
  func addObserver() {
    NotificationCenter
      .default
      .addObserver(
        self,
        selector: #selector(self.keyboardWillChangeFrame),
        name: UIResponder.keyboardWillChangeFrameNotification,
        object: nil)
  }

  // キーボードの監視終了
  func removeObserver() {
    NotificationCenter
      .default
      .removeObserver(self,
                      name: UIResponder.keyboardWillChangeFrameNotification,
                      object: nil)
  }

  // キーボードのフレーム検知処理
  @objc
  func keyboardWillChangeFrame(_ notification: Notification) {
    if let endFrame = notification
      .userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue,
    let beginFrame = notification
      .userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue {
      let endFrameMinY: CGFloat = endFrame.cgRectValue.minY
      let beginFrameMinY: CGFloat = beginFrame.cgRectValue.minY

      self.keyboardHeight = beginFrameMinY - endFrameMinY
        if self.keyboardHeight < 0 {
        self.keyboardHeight = 0
      }
    }
  }
}

これで下準備は完了です。

利用例(全体適用)

Sample.swift

struct HogeView: View {

    @State var inputText = ""
    @ObservedObject var keyboard = KeyboardObserver()

    var body: some View {
        VStack {
            TextField("入力1", text: $inputText)
            .onAppear{
                self.keyboard.addObserver()
            }.onDisappear{
                self.keyboard.removeObserver()
            }.padding(.bottom, keyboard.keyboardHeight)
        }
    }
}

onAppearとonDisappearでは、Viewが表示されたときにキーボードの高さを監視していて、Viewが非表示になった段階で監視を終わらせています。
※シュミレーターで表示させないとキーボードの挙動を確認できません

利用例(個別適用)

Sample.swift

struct HogeView: View {

    @State var inputText = ""
    @State var inputText_2 = ""
    @State var inputText_3 = ""
    @ObservedObject var keyboard = KeyboardObserver()

    var body: some View {
        VStack {
            //1
            TextField("入力1", text: $inputText)
            //2
            TextField("入力2", text: $inputText_2)
            //3(ここに適用)
            TextField("入力3", text: $inputText_3)
        }
    }
}

上記コードの三つ目のTextFieldにのみキーボードの操作を適用させたい場合は以下のように記述します。

Sample.swift

struct HogeView: View {

    @State var inputText = ""
    @State var inputText_2 = ""
    @State var inputText_3 = ""
    @ObservedObject var keyboard = KeyboardObserver()

    var body: some View {
        VStack {
            //1
            TextField("入力1", text: $inputText)
            //2
            TextField("入力2", text: $inputText_2)
            //3(ここに適用)
            TextField("入力3", text: $inputText_3, onEditingChanged: {
                begin in

                if begin {
                    self.keyboard.addObserver()
                } else {
                    self.keyboard.removeObserver()
                }

            })
        }.padding(.bottom, keyboard.keyboardHeight)
    }
}

TextFieldのonEditingChangedでBoolで管理します。三つ目のTextFieldに対して入力操作が始まったときにキーボードの監視を開始し、入力が終わったら終了するようにしています。

まとめ

備忘録的な要素が強く、抜けがあると思いますがご容赦ください。
TextFieldがいくつもある場合に、個別適用を用いることが多くなりそうです。

参考記事

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3