はじめに
UITextField
や UITextView
で入力する際はキーボードの入力タイプが色々用意されていますが実はこのキーボード色々カスタムができます!
たぶん実用的なのは UIPickerView
とか UIDatePicker
を表示したりとかです(なんか昔半角カナ用キーボードを作った記憶があるけどあんまよくなかった)。
これからはもう UIKit
を使うことも少なくなっていくのかもしれませんが備忘録として。。。
*注:「つくろう」って書きましたがとくにカスタムキーボードを薦めるものではありません。
UITextFieldをカスタマイズ
試しに UITextField
のキーボードをカスタムしてみます。やり方は簡単で inputView
に任意の View
を設定するだけで OK です
// こんなのとか
let keyboard = CustomKeyboardView(frame: .init(origin: .zero, size: .init(width: 284, height: 284)))
keyboard.delegate = self
textField.inputView = keyboard
// こんなのとか
let picker = UIPickerView()
picker.delegate = self
picker.dataSource = self
textField.inputView = picker
あとはデリゲートとかで入力文字を受け取って UITextField
に表示するだけです。
こんな感じ。
カスタム View | ピッカー |
---|---|
![]() |
![]() |
カスタム View はこんな感じです。
xib

protocol CustomKeyboardViewDelegate: AnyObject {
func customKeyboardView(_ customKeyboardView: CustomKeyboardView, didSelectKey key: String)
}
final class CustomKeyboardView: UIView {
weak var delegate: CustomKeyboardViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
loadNib()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
loadNib()
}
private func loadNib() {
let view = Bundle.main.loadNibNamed("CustomKeyboardView", owner: self, options: nil)?.first as! UIView
view.frame = bounds
view.translatesAutoresizingMaskIntoConstraints = true
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
addSubview(view)
}
@IBAction private func selectKey(_ sender: UIButton) {
delegate?.customKeyboardView(self, didSelectKey: sender.titleLabel!.text!)
}
}
キーボードの高さはわりと自由みたいです

サクッとカスタムキーボードが表示できました!ただカスタムキーボードを入力制限目的で利用するにはいくつか問題があるのでオススメしませんコピペとか外部キーボード接続とか。。。
コピペに関しては UITextField
のカスタムクラスをつくって canPerformAction
ごにょごにょすればいける気がしますが外部キーボードに関しては防げないと思われます(そもそもあんまり UITextField
で入力制限なんてしない方がいいと思います)。
UIControlをカスタマイズ
とくに UITextField
の inputView
に設定する!でも問題ないのですが UITextField
を使うとなるとレイアウトの自由度が低いのでせっかくなんでカスタムクラスをつくった方が自由度が高いのでおすすめです
下記のように UIControl
を継承したクラスをつくって canBecomeFirstResponder
と inputView
を設定してやるとカスタムキーボードが表示できます。UIView
じゃないのは addAction
がしたかったからです。フォーカス時がわかりにくいので枠線の色を変更しています。
protocol PickerInputControlDelegate: AnyObject {
func pickerInputControl(_ pickerInputControl: PickerInputControl, didSelectValue value: String)
}
final class PickerInputControl: UIControl {
var items = [String]()
weak var delegate: PickerInputControlDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
commonInit()
}
private func commonInit() {
layer.cornerRadius = 8.0
layer.borderWidth = 1.0
layer.borderColor = UIColor.systemGray.cgColor
addAction(.init(handler: { [weak self] _ in
self?.isSelected.toggle()
if self?.isSelected == true {
self?.becomeFirstResponder()
} else {
self?.resignFirstResponder()
}
}), for: .touchUpInside)
}
override var inputView: UIView? {
let picker = UIPickerView()
picker.delegate = self
picker.dataSource = self
return picker
}
override var canBecomeFirstResponder: Bool {
return true
}
override var isSelected: Bool {
didSet {
layer.borderColor = isSelected ? UIColor.systemBlue.cgColor : UIColor.systemGray.cgColor
}
}
@discardableResult
override func becomeFirstResponder() -> Bool {
let value = super.becomeFirstResponder()
isSelected = isFirstResponder
return value
}
@discardableResult
override func resignFirstResponder() -> Bool {
let value = super.resignFirstResponder()
isSelected = isFirstResponder
return value
}
}
extension PickerInputControl: UIPickerViewDelegate {
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
delegate?.pickerInputControl(self, didSelectValue: items[row])
}
}
extension PickerInputControl: UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return items.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return items[row]
}
}
こんな感じで UIControl
なので中に View
置き放題です。

UIPickerViewDelegate
, UIPickerViewDataSource
, items
は外に出した方が汎用性が高いかも
static cellと組み合わせる
おまけで UITableViewController
の static cell と組み合わせるとフォーカス時に自動スクロールしてくれるので複数の入力項目がある場合はおすすめです
こんな感じ。
おわりに
カスタムキーボードを作る際はタップ領域をちゃんと確保してあげると素敵です。ちょっと古い記事ですが下記の記事はキーボードのタップ領域とか詳しく調べていておもしろいです。
わりとお世話になった手法だけどこれからはあんまり使わなくなるのかな UIKit
。。。
調べてて気になったけどこいつ知らねえ
