SwiftUIでキーボードで文字が隠れないように処理をいれる


UIKit同様にキーボードが閉じる処理は元々入っていない

  • iOSの開発をすると必ず直面するキーボードを閉じる処理。
  • Returnキーを押したときや、他の箇所をタップした時に閉じたり、キーボードで入力される文字が隠れないように自分で処理を作成しなければならない。
  • 今回はキーボードで入力される文字が隠れないようにする処理を作成する
  • UIKitの時と同様にNotificationCenterを使ってキーボードの監視を行う。

実装

キーボードを監視するクラス


import SwiftUI
import Combine

class KeyboardObserver: ObservableObject {

  @Published var keyboardHeight: CGFloat = 0.0

  /// Observerの追加
  func addObserver() {
    NotificationCenter
      .default
      .addObserver(self,
                   selector: #selector(self.keyboardWillChangeFrame(_:)),
                   name: UIResponder.keyboardWillChangeFrameNotification,
                   object: nil)
  }

  /// Observerの削除
  func removeObserver() {
    NotificationCenter
      .default
      .removeObserver(self,
                      name: UIResponder.keyboardWillChangeFrameNotification,
                      object: nil)
  }

  /// キーボードのフレーム検知処理
  /// - Parameter notification: Notification
  @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
      }
    }
  }

}

Viewのクラス

struct ContentView: View {

  @ObservedObject var keyboard = KeyboardObserver()
  @State var text: String = ""

  var body: some View {
    VStack {
      Spacer()
      Rectangle()
        .frame(width: 300, height: 300)
      TextField("入力", text: self.$text)
        .padding()
    }.onAppear(perform: {
      self.keyboard.addObserver()
    }).onDisappear(perform: {
      self.keyboard.removeObserver()
    }).padding(.bottom,
               self.keyboard.keyboardHeight)
      .animation(.easeOut)
  }

}

実行結果

まとめ

  • SwiftUIでも文字が隠れないように処理を入れることができた。
  • つぎは他の箇所をタップした際にも閉じられる処理を掲載する。