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!
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 9.2, swift 4
- Xcode 10.2.1 (10E1001), 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 = UIBarButtonItem(title: "back", style: .plain, target: target, action: action)
case .backDisabled:
button = UIBarButtonItem(title: "back", style: .plain, target: target, action: action)
button.isEnabled = false
case .forward:
button = UIBarButtonItem(title: "forward", style: .plain, target: target, action: action)
case .forwardDisabled:
button = UIBarButtonItem(title: "forward", style: .plain, target: target, action: action)
button.isEnabled = false
case .done:
button = UIBarButtonItem(title: "done", style: .plain, target: target, action: action)
case .cancel:
button = UIBarButtonItem(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, tappedIn toolbar: KeyboardToolbar)
}
class KeyboardToolbar: UIToolbar {
weak var toolBarDelegate: KeyboardToolbarDelegate?
init() {
super.init(frame: .zero)
barStyle = UIBarStyle.default
isTranslucent = true
sizeToFit()
isUserInteractionEnabled = true
}
func setup(leftButtons: [KeyboardToolbarButton], rightButtons: [KeyboardToolbarButton]) {
let leftBarButtons = leftButtons.map { (item) -> UIBarButtonItem in
return item.createButton(target: self, action: #selector(buttonTapped))
}
let rightBarButtons = rightButtons.map { (item) -> UIBarButtonItem in
return item.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) {
if let type = KeyboardToolbarButton.detectType(barButton: sender) {
toolBarDelegate?.keyboardToolbar(button: sender, type: type, tappedIn: self)
}
}
}
Full example of usage
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
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
let toolbar = KeyboardToolbar()
toolbar.toolBarDelegate = self
toolbar.setup(leftButtons: leftButtons, rightButtons: rightButtons)
textField.inputAccessoryView = toolbar
view.addSubview(textField)
}
}
extension ViewController: KeyboardToolbarDelegate {
func keyboardToolbar(button: UIBarButtonItem, type: KeyboardToolbarButton, tappedIn toolbar: KeyboardToolbar) {
print("Tapped button type: \(type)")
}
}
Results
Changes to make to your code:
- Give
accessoryView
a height - Delete
var myView: customUIView
& the entireviewDidLoad()
override
Try this.
override var inputAccessoryView: UIView? {
get {
return containerView
}
}
override var canBecomeFirstResponder: Bool {
return true
}
来源:https://stackoverflow.com/questions/35689528/add-a-view-on-top-of-the-keyboard-using-inputaccessoryview-swift