add a view on top of the keyboard using InputAccessoryView swift
To get a view to stick above the keyboard, the code itself is pretty simple. The code you posted is not correct, try this (note that you must connect textField
to the UITextField
in your storyboard):
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
let customView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 44))
customView.backgroundColor = UIColor.red
textField.inputAccessoryView = customView
}
Details
- Xcode 11.2 (11B52), Swift 5
Solution
KeyboardToolbarButton
import UIKit
enum KeyboardToolbarButton: Int {
case done = 0
case cancel
case back, backDisabled
case forward, forwardDisabled
func createButton(target: Any?, action: Selector?) -> UIBarButtonItem {
var button: UIBarButtonItem!
switch self {
case .back: button = .init(title: "back", style: .plain, target: target, action: action)
case .backDisabled:
button = .init(title: "back", style: .plain, target: target, action: action)
button.isEnabled = false
case .forward: button = .init(title: "forward", style: .plain, target: target, action: action)
case .forwardDisabled:
button = .init(title: "forward", style: .plain, target: target, action: action)
button.isEnabled = false
case .done: button = .init(title: "done", style: .plain, target: target, action: action)
case .cancel: button = .init(title: "cancel", style: .plain, target: target, action: action)
}
button.tag = rawValue
return button
}
static func detectType(barButton: UIBarButtonItem) -> KeyboardToolbarButton? {
return KeyboardToolbarButton(rawValue: barButton.tag)
}
}
KeyboardToolbar
import UIKit
protocol KeyboardToolbarDelegate: class {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, isInputAccessoryViewOf textField: UITextField)
}
class KeyboardToolbar: UIToolbar {
private weak var toolBarDelegate: KeyboardToolbarDelegate?
private weak var textField: UITextField!
init(for textField: UITextField, toolBarDelegate: KeyboardToolbarDelegate) {
super.init(frame: .init(origin: .zero, size: CGSize(width: UIScreen.main.bounds.width, height: 44)))
barStyle = .default
isTranslucent = true
self.textField = textField
self.toolBarDelegate = toolBarDelegate
textField.inputAccessoryView = self
}
func setup(leftButtons: [KeyboardToolbarButton], rightButtons: [KeyboardToolbarButton]) {
let leftBarButtons = leftButtons.map {
$0.createButton(target: self, action: #selector(buttonTapped))
}
let rightBarButtons = rightButtons.map {
$0.createButton(target: self, action: #selector(buttonTapped(sender:)))
}
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
setItems(leftBarButtons + [spaceButton] + rightBarButtons, animated: false)
}
required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
@objc func buttonTapped(sender: UIBarButtonItem) {
guard let type = KeyboardToolbarButton.detectType(barButton: sender) else { return }
toolBarDelegate?.keyboardToolbar(button: sender, type: type, isInputAccessoryViewOf: textField)
}
}
extension UITextField {
func addKeyboardToolBar(leftButtons: [KeyboardToolbarButton],
rightButtons: [KeyboardToolbarButton],
toolBarDelegate: KeyboardToolbarDelegate) {
let toolbar = KeyboardToolbar(for: self, toolBarDelegate: toolBarDelegate)
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
}
}
Usage
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
textField.addKeyboardToolBar(leftButtons: [.back, .forwardDisabled], rightButtons: [.done], toolBarDelegate: self)
}
}
extension ViewController: KeyboardToolbarDelegate {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, isInputAccessoryViewOf textField: UITextField) {
print("Tapped button type: \(type) | \(textField)")
}
}
Full example of usage
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createTextField(frame: CGRect(x: 50, y: 50, width: 200, height: 40), leftButtons: [.backDisabled, .forward], rightButtons: [.cancel])
createTextField(frame: CGRect(x: 50, y: 120, width: 200, height: 40), leftButtons: [.back, .forwardDisabled], rightButtons: [.done])
}
private func createTextField(frame: CGRect, leftButtons: [KeyboardToolbarButton] = [], rightButtons: [KeyboardToolbarButton] = []) {
let textField = UITextField(frame: frame)
textField.borderStyle = .roundedRect
view.addSubview(textField)
textField.addKeyboardToolBar(leftButtons: leftButtons, rightButtons: rightButtons, toolBarDelegate: self)
}
}
extension ViewController: KeyboardToolbarDelegate {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, isInputAccessoryViewOf textField: UITextField) {
print("Tapped button type: \(type) | \(textField)")
}
}
Xcode 11.2 layout problem
- https://github.com/hackiftekhar/IQKeyboardManager/issues/1616
Results
Try this.
override var inputAccessoryView: UIView? {
get {
return containerView
}
}
override var canBecomeFirstResponder: Bool {
return true
}