Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a view on top of the keyboard using InputAccessoryView

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!

like image 583
user101010 Avatar asked Feb 28 '16 23:02

user101010


People also ask

What is Inputaccessoryview in Swift?

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.


2 Answers

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 } 
like image 51
paulvs Avatar answered Oct 13 '22 23:10

paulvs


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

enter image description here


enter image description here


enter image description here

like image 38
Vasily Bodnarchuk Avatar answered Oct 13 '22 23:10

Vasily Bodnarchuk