简体   繁体   中英

UITextView in InputAccessoryView not becoming First Responder (Keyboard does not show up initially)

I'm trying to implement an input accessory view that works just like Messages app in iOS. I've searched almost every SO questions regarding this topic, but couldn't find the solution that worked for me.

Here is the minimal reproducible code I created, referring to this SO post .

import UIKit

class TestViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        becomeFirstResponder()  // seems unnecessary
    }
    
    override var inputAccessoryView: UIToolbar {
        return self.keyboardAccessory
    }
    
    override var canBecomeFirstResponder: Bool {
        return true
    }

    var textView: UITextView = {
        let view = UITextView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = .yellow
        return view
    }()
    
    lazy var keyboardAccessory: UIToolbar = {
        let inputAccessory = UIToolbar(frame: .init(x: 0, y: 0, width: 0, height: 100))
        inputAccessory.addSubview(textView)
        NSLayoutConstraint.activate([
            textView.centerXAnchor.constraint(equalTo: inputAccessory.centerXAnchor),
            textView.centerYAnchor.constraint(equalTo: inputAccessory.centerYAnchor),
            textView.widthAnchor.constraint(equalToConstant: 200),
            textView.heightAnchor.constraint(equalToConstant: 50)
        ])
        inputAccessory.backgroundColor = .gray
        return inputAccessory
    }()
}

Every article I've seen suggests overriding inputAccessoryView and canBecomeFirstResponder , and that's it. However, the keyboard does not appear until I tap the textView .

Can anyone let me know what I'm missing?

Actually when you override canBecomeFirstResponder the keyboard is appear just under the view, thats why you only see the accessory view bottom side of the view. You can basically try this with adding notification to your controller like

 override func viewDidLoad() {
    super.viewDidLoad()

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:UIResponder.keyboardWillHideNotification, object: nil)

}

 @objc func keyboardWillShow(notification:NSNotification) {

    let userInfo = notification.userInfo!
    let keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    print(keyboardFrame)
    print(self.view.frame)
}

When you run the project, you gonna see the keyboardWillShow notification is hired.(If you delete overiride canBecomeFirstResponder it won't )

And when you print keyboard and view frame, you gonna notice to keyboard's y position is equal to view's frame height. That means keyboards want to show us only its accessoryView.

So, you need to hired textView.becomeFirstResponder() in keyboardWillShow notification

@objc func keyboardWillShow(notification:NSNotification) {

    let userInfo = notification.userInfo!
    let keyboardFrame:CGRect = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    textView.becomeFirstResponder()
}

Do not forget to deinit notification when controller deinit

  deinit {
    NotificationCenter.default.removeObserver(self)
}

If you want the text view to become active, and the keyboard to show, as soon as the view appears , use:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    textView.becomeFirstResponder()
}

If you want the text view to be visible at the bottom, and become active / show the keyboard when the textview is tapped, take a look at this answer:

https://stackoverflow.com/a/61508928/6257435

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM