使用键盘使带有 TextField 的 UIToolbar 向上移动

Posted

技术标签:

【中文标题】使用键盘使带有 TextField 的 UIToolbar 向上移动【英文标题】:Making UIToolbar with TextField move up with keyboard 【发布时间】:2015-10-13 21:27:34 【问题描述】:

我有一个带有 TextField 的 UIToolbar 和一个作为 UIBarButtonItem 的按钮。当用户点击工具栏中的 TextField 时,我正在尝试将此工具栏用作键盘的 inputAccessory。

我发现this question 试图解决同样的问题。不幸的是,该解决方案无效。

我正在尝试的是:

class ChatViewController: UIViewController, CLLocationManagerDelegate, UITableViewDelegate, UITableViewDataSource 

    @IBOutlet weak var chatTableView: UITableView!
    @IBOutlet weak var chatToolbar: UIToolbar!

    @IBOutlet weak var textFieldBarButtonItem: UIBarButtonItem!

    override func viewDidAppear(animated: Bool) 
        super.viewDidLoad()
        self.chatTableView.delegate = self
        self.chatTableView.dataSource = self
        self.chatToolbar.removeFromSuperview()

    

    override var inputAccessoryView: UIView
        get
            return self.chatToolbar
        
    

    override func canBecomeFirstResponder() -> Bool 
        return true
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

        let cell = UITableViewCell()
        return cell
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

        return 0
    


而我得到的是:

*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 
'child view controller:<UICompatibilityInputViewController: 0x13ff34e00> should have parent view controller:
<App.ChatViewController: 0x13ff21cc0> but requested parent is:<UIInputWindowController: 0x1400b4600>'

有什么想法吗?

【问题讨论】:

这个方法不错,问题应该是inputAccessoryView:viewDidAppear之前被调用了。附件视图不应属于任何视图层次结构。顺便说一句:接受的答案也可以 @Omer 太好了,你有什么建议? 我认为这两种方法都很好,我更喜欢accessoryInputView,因为它在其他好处之间更清晰(即:使用UIScrollViewKeyboardDismissModeInteractive的更简单方法,独立于故事板/xib,无约束=D)。以下链接包含一个 obj-c 项目,它使用附件视图方法进行了基本实现,以防万一你想尝试一下:dropbox.com/s/a4bsvz0ie95i3qn/KeyboardAccessory.zip?dl=0 |||不是我在使用工具栏,但你可以使用任何你想要的 UIView 子类 我的意思是,我应该如何继续强制在 viewDidAppear 之后调用 inputAccessoryView 不知道你为什么需要它,inputAccessoryView 是 UIResponder 的一个属性(因此,也是 UIViewController 的一个属性)。此类的基本实现使用此属性以便在需要时提供自定义行为。检查我分享的项目。 【参考方案1】:

第一件事:

    您应该为 Storyboard 中的工具栏创建约束(左、下、右)。 在视图控制器中为底部约束创建一个出口(从情节提要中拖动)。保存初始约束值(键盘消失时恢复) 创建观察者以了解您的键盘何时出现和消失(3.1 并创建轻击手势以隐藏您的键盘) 当键盘 4.1 出现而 4.2 消失时,您只会更改底部约束值(键盘大小)。您也可以为工具栏设置动画。

类似:

class ChatViewController: UIViewController, CLLocationManagerDelegate, UITableViewDelegate, UITableViewDataSource 

    @IBOutlet weak var chatTableView: UITableView!
    @IBOutlet weak var chatToolbar: UIToolbar!

    @IBOutlet weak var textFieldBarButtonItem: UIBarButtonItem!

    //2
    @IBOutlet weak var toolbarBottomConstraint: NSLayoutConstraint!
    var toolbarBottomConstraintInitialValue: CGFloat?

    override func viewDidAppear(animated: Bool) 
        super.viewDidAppear(animated)
        self.chatTableView.delegate = self
        self.chatTableView.dataSource = self
        self.chatToolbar.removeFromSuperview()

        //2
        self.toolbarBottomConstraintInitialValue = toolbarBottomConstraint.constant
        //3
        enableKeyboardHideOnTap()

    

    // 3
    // Add a gesture on the view controller to close keyboard when tapped
    private func enableKeyboardHideOnTap()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) // See 4.1
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) //See 4.2            

        // 3.1
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")

        self.view.addGestureRecognizer(tap)
    

    //3.1
    func hideKeyboard() 
        self.view.endEditing(true)
    

    //4.1
    func keyboardWillShow(notification: NSNotification) 

        let info = notification.userInfo!

        let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double        

        UIView.animateWithDuration(duration)  () -> Void in

            self.toolbarBottomConstraint.constant = keyboardFrame.size.height + 5

            self.view.layoutIfNeeded()

        

    

    //4.2
    func keyboardWillHide(notification: NSNotification) 

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double

        UIView.animateWithDuration(duration)  () -> Void in

            self.toolbarBottomConstraint.constant = self.toolbarBottomConstraintInitialValue!
            self.view.layoutIfNeeded()

        

    

    override var inputAccessoryView: UIView
        get
            return self.chatToolbar
        
    

    override func canBecomeFirstResponder() -> Bool 
        return true
    

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

        let cell = UITableViewCell()
        return cell
    

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

        return 0
    


希望对你有帮助!

【讨论】:

以上是关于使用键盘使带有 TextField 的 UIToolbar 向上移动的主要内容,如果未能解决你的问题,请参考以下文章

使用带有 TextField 的自定义表格视图单元格关闭数字键盘

键盘出现/消失时调整带有 TextField 的 SwiftUI 列表

当键盘出现并启用滚动时,TextField 向上移动

带有动画的 TextField 使应用程序崩溃并失去焦点

在带有约束的 UIScrollView 底部放置一个 UIButton

Flutter TextField被键盘隐藏,尝试了很多解决方案但不起作用