I'm trying to add a uiview to be on top of the keyboard always. I did it first with KeyboardWillShow/Hide, but it dosen't cover all cases and I'm trying to use inputAccesoryView. this is what I tried:
private var accessoryView = UIView(frame: CGRectZero) class ViewController : UIViewController { var myView: customUIView override var inputAccessoryView: UIView { return accessoryView } override func canBecomeFirstResponder() -> Bool { return true } override func viewDidLoad() { super.viewDidLoad() accessoryView = myView } }
I get the following error :
Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:UICompatibilityInputViewController should have parent view controller:MyViewController but requested parent is: UIInputWindowController: '
any help will be appreciated!
A component which enables customization of the keyboard input accessory view on iOS. The input accessory view is displayed above the keyboard whenever a TextInput has focus. This component can be used to create custom toolbars.
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 }
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) } }
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)") } }
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)") } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With