Search code examples
swiftuiscrollviewscrollviewswift5

Keyboard covers UITextView


I have an extension which scrolls the scrollView up so it does not cover UITextField, however for UITextView it does not scroll up. The extension looks like this:

extension SummaryViewController {
    
    ///Register for keyboard willHide willShow notifiication
    func registerKeyboardNotifications() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(SummaryViewController.keyboardNotification(notification:)),
                                               name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    }
    
    @objc func keyboardNotification(notification: NSNotification) {
        
        if let userInfo = notification.userInfo {
            let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
            let duration: TimeInterval = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
            let animationCurve: UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
            
            if (endFrame?.origin.y)! >= UIScreen.main.bounds.size.height {
                //close keyboard
                
                scrollView.contentInset = .zero
                
            } else {
                //open keyboard
                let height: CGFloat = (notification.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)!.size.height
                scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: height, right: 0)
            }
            
            UIView.animate(withDuration: duration,
                           delay: TimeInterval(0),
                           options: animationCurve,
                           animations: { self.view.layoutIfNeeded() },
                           completion: nil)
        }
    }
}


I call registerKeyboardNotifications() in viewDidLoad.


Solution

  • For UITextView it doesn't work, so i do this with contentOffset.

    Swift 5

    extension SummaryViewController {
        
        private func registerKeyboardNotifications() {
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIControl.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIControl.keyboardWillHideNotification, object: nil)
        }
    
        @objc func keyboardWillShow(_ notification: Notification) {
            guard let keyboardFrameValue = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue else { return }
            let keyboardFrame = view.convert(keyboardFrameValue.cgRectValue, from: nil)
            scrollView.contentOffset = CGPoint(x: 0, y: keyboardFrame.size.height)
        }
    
        @objc func keyboardWillHide(_ notification: Notification) {
            scrollView.contentOffset = .zero
        }
    }