使用 InputAccessoryView 在键盘顶部添加一个视图
Add a view on top of the keyboard using InputAccessoryView
我正在尝试将 uiview 添加到始终位于键盘顶部的位置。
我先用 KeyboardWillShow/Hide 做了它,但它并没有涵盖所有
案例,我正在尝试使用 inputAccessoryView。
这是我试过的:
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
}
}
我收到以下错误:
Terminating app due to uncaught exception
'UIViewControllerHierarchyInconsistency', reason: 'child view
controller:UICompatibilityInputViewController should have parent view
controller:MyViewController but requested parent is:
UIInputWindowController: '
任何帮助将不胜感激!
要将视图固定在键盘上方,代码本身非常简单。您发布的代码不正确,试试这个(注意您必须将 textField
连接到故事板中的 UITextField
):
@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
}
对您的代码所做的更改:
- 给
accessoryView
一个高度
- 删除
var myView: customUIView
和整个 viewDidLoad()
覆盖
详情
- Xcode11.2 (11B52),Swift5
解决方案
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 {
[=11=].createButton(target: self, action: #selector(buttonTapped))
}
let rightBarButtons = rightButtons.map {
[=11=].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)")
}
}
Xcode 11.2布局问题
结果
试试这个。
override var inputAccessoryView: UIView? {
get {
return containerView
}
}
override var canBecomeFirstResponder: Bool {
return true
}
我正在尝试将 uiview 添加到始终位于键盘顶部的位置。 我先用 KeyboardWillShow/Hide 做了它,但它并没有涵盖所有 案例,我正在尝试使用 inputAccessoryView。 这是我试过的:
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
}
}
我收到以下错误:
Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:UICompatibilityInputViewController should have parent view controller:MyViewController but requested parent is: UIInputWindowController: '
任何帮助将不胜感激!
要将视图固定在键盘上方,代码本身非常简单。您发布的代码不正确,试试这个(注意您必须将 textField
连接到故事板中的 UITextField
):
@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
}
对您的代码所做的更改:
- 给
accessoryView
一个高度 - 删除
var myView: customUIView
和整个viewDidLoad()
覆盖
详情
- Xcode11.2 (11B52),Swift5
解决方案
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 {
[=11=].createButton(target: self, action: #selector(buttonTapped))
}
let rightBarButtons = rightButtons.map {
[=11=].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)")
}
}
Xcode 11.2布局问题
结果
试试这个。
override var inputAccessoryView: UIView? {
get {
return containerView
}
}
override var canBecomeFirstResponder: Bool {
return true
}