はじめに
私は現在カスタムキーボードを作成していて、キーボードの状態を知る方法を色々試しています。
この方法はCustomKeyboardExtensionでは使用できませんでしたが、メインターゲットでは使用できました。
せっかく試したので記事にしておきます。
サンプルアプリ
ちょっと見にくいですが、以下の2項目を表示しています。
実装
View
ContentView
import SwiftUI
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
NavigationStack {
List {
TextField("タップしてください", text: $viewModel.text)
LabeledContent {
Text(viewModel.keyboardStatus.rowValue)
} label: {
Text("状態")
}
LabeledContent {
Text(viewModel.keyboardRect.size.debugDescription)
} label: {
Text("サイズ")
}
Button {
viewModel.closeKeyboard()
} label: {
Text("キーボードを閉じる")
}
}
.navigationTitle("キーボード監視")
}
}
}
ViewModel
ViewModel
import Combine
import UIKit
final class ViewModel: ObservableObject {
@Published var text: String = ""
@Published var keyboardStatus: KeyboardStatus = .hide
@Published var keyboardRect: CGRect = .zero
private let notificationCenter = NotificationCenter.default
private var cancellable = Set<AnyCancellable>()
init() {
notificationCenter.publisher(for: UIResponder.keyboardDidChangeFrameNotification)
.sink { [weak self] notification in
guard
let self,
let userInfo = notification.userInfo,
let rect = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
else { return }
self.keyboardRect = rect
if rect == .zero {
self.keyboardStatus = .hide
} else {
self.keyboardStatus = .show
}
}
.store(in: &cancellable)
}
func closeKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
Model
KeyboardStatus
import Foundation
enum KeyboardStatus {
case show
case hide
var rowValue: String {
switch self {
case .show:
return "開いている"
case .hide:
return "閉じている"
}
}
}