使用UITextField创建UIToolbar并随键盘一起上移

4

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

enter image description here

我发现了这个问题,它试图解决相同的问题。不幸的是,解决方案并不有效。

我尝试的是:

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
@Omer 很好,你有什么建议? - adolfosrs
1
我认为这两种方法都可以,但我更喜欢accessoryInputView,因为它更简洁,而且有其他好处(例如:更容易使用UIScrollViewKeyboardDismissModeInteractive,独立于storyboard/xib,没有约束问题)。以下链接包含一个obj-c项目,使用accessory view方法实现了基本功能,你可以尝试一下:https://www.dropbox.com/s/a4bsvz0ie95i3qn/KeyboardAccessory.zip?dl=0 ||| 我正在使用工具栏,但你可以使用任何UIView子类。 - Omer
我的意思是,我应该如何在viewDidAppear之后强制调用inputAccessoryView - adolfosrs
不确定为什么您需要那个,inputAccessoryView是UIResponder的属性(因此也是UIViewController的属性)。该类的基本实现使用此属性以提供必要的自定义行为。请查看我分享的项目。 - Omer
你是如何为文本框和按钮设置完美的约束条件的? - Abhishek Biswas
1个回答

11

首先:

  1. 你应该在Storyboard中创建Toolbar的约束(左、底部、右)。
  2. 为视图控制器中的底部约束创建一个Outlet(从Storyboard中拖动)。保存初始约束值(以便在键盘消失时恢复)。
  3. 创建一个观察者来知道你的键盘何时出现和消失(3.1并创建一个轻击手势来隐藏你的键盘)。
  4. 当键盘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
    }

}

希望这有所帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接