Scroll UITextField above Keyboard in a UITableViewCell on a regular UIViewController

前端 未结 10 1083
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 14:17

I have tried most of the examples here on StackOverflow. I also used Apple\'s. The problem I seem to have with them is that they don\'t account for the UITextField being in

10条回答
  •  春和景丽
    2020-11-27 14:28

    I did a mix between the answer of @Victor and some code that I had. I created a handy extension that can be use across many UITextField.

    1.- First we need an extension for the UITextField to manage the keyboard notifications

    extension UITextField {
    
        func keepTextFieldAboveKeyboard(tableView:UITableView) {
    
            var willShowNotification: NSObjectProtocol?
            var willHideNotification: NSObjectProtocol?
    
            willShowNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in
    
                var userInfo = notification.userInfo!
    
                if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                    // Get my height size
                    let myheight = tableView.frame.height
                    // Get the top Y point where the keyboard will finish on the view
                    let keyboardEndPoint = myheight - keyboardFrame.height
                    // Get the the bottom Y point of the textInput and transform it to the currentView coordinates.
                    if let pointInTable = self.superview?.convert(self.frame.origin, to: tableView) {
    
                        let textFieldBottomPoint = pointInTable.y + self.frame.size.height + 20
    
                        // Finally check if the keyboard will cover the textInput
                        if keyboardEndPoint <= textFieldBottomPoint {
    
                            tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint
                        } else {
    
                            tableView.contentOffset.y = 0
                        }
                    }
                }
    
                NotificationCenter.default.removeObserver(willShowNotification!)
            }
    
            willHideNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in
    
                tableView.contentOffset.y = 0
    
                NotificationCenter.default.removeObserver(willHideNotification!)
            }
    
        }
    
    }
    

    2.- This previous extension should be call inside textFieldShouldBeginEditing so we can have an extension for that as well

    extension UITextField : UITextFieldDelegate {
    
        public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool  {
    
            guard let tableView = textField.parentView(of: UITableView.self) else { return true };
    
            textField.keepTextFieldAboveKeyboard(tableView:tableView);
    
            return true;
    
        }
    }
    

    3.- Finally as you notice in the previous method, we need the TableView where the cell with the UITextField is located. So we can use this extension (Which is also useful for other purposes)

    extension UIView {
        func parentView(of type: T.Type) -> T? {
            guard let view = self.superview else {
                return nil
            }
            return (view as? T) ?? view.parentView(of: T.self)
        }
    }
    

    4.- Finally in the cell where the UITextField is located, we just write this simple line of code

    textField.delegate = textField;
    

    Completely reusable and universal.

提交回复
热议问题