问题
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!
回答1:
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
}
回答2:
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
回答3:
Changes to make to your code:
- Give
accessoryView
a height - Delete
var myView: customUIView
& the entireviewDidLoad()
override
回答4:
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