Get UITableView to scroll to the selected UITextField and Avoid Being Hidden by Keyboard

后端 未结 13 1014
鱼传尺愫
鱼传尺愫 2020-11-29 17:47

I have a UITextField in a table view on a UIViewController (not a UITableViewController). If the table view is on a UITableViewC

13条回答
  •  北荒
    北荒 (楼主)
    2020-11-29 18:28

    Swift

    @objc private func keyboardWillShow(_ notification: Notification) {
        guard let userinfo = notification.userInfo else {
            return
        }
    
        guard
            let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
            let endFrame = (userinfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
            let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
                return
        }
        
        UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
            let edgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: endFrame.height, right: 0)
            self.scrollView.contentInset = edgeInsets
            self.scrollView.scrollIndicatorInsets = edgeInsets
        })
    }
    
    @objc private func keyboardWillHide(_ notification: Notification) {
        guard let userinfo = notification.userInfo else {
            return
        }
    
        guard
            let duration = (userinfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
            let curveOption = userinfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? UInt else {
                return
        }
        
        UIView.animate(withDuration: duration, delay: 0, options: [.beginFromCurrentState, .init(rawValue: curveOption)], animations: {
            let edgeInsets = UIEdgeInsets.zero
            self.scrollView.contentInset = edgeInsets
            self.scrollView.scrollIndicatorInsets = edgeInsets
        })
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ...
    
        subscribeToKeyboardNotifications()
    }
    
    deinit {
        unsubscribeFromKeyboardNotifications()
    }
    
    private func subscribeToKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIWindow.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIWindow.keyboardWillHideNotification, object: nil)
    }
    
    private func unsubscribeFromKeyboardNotifications() {
        NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIWindow.keyboardWillHideNotification, object: nil)
    }
    

    Objective C

    - (void)keyboardWillShow:(NSNotification *)sender
    {
        CGFloat height = [[sender.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
        NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
        
        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
            UIEdgeInsets edgeInsets = UIEdgeInsetsMake(0, 0, height, 0);
            tableView.contentInset = edgeInsets;
            tableView.scrollIndicatorInsets = edgeInsets;
        } completion:nil];
    }
    
    - (void)keyboardWillHide:(NSNotification *)sender
    {
        NSTimeInterval duration = [[sender.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        UIViewAnimationOptions curveOption = [[sender.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue] << 16;
    
        [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState|curveOption animations:^{
            UIEdgeInsets edgeInsets = UIEdgeInsetsZero;
            tableView.contentInset = edgeInsets;
            tableView.scrollIndicatorInsets = edgeInsets;
        } completion:nil];
    }
    

    And in - (void)viewDidLoad

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    

    Then

    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
    

提交回复
热议问题