dehlen
dehlen

Reputation: 7391

UIScrollView scroll to button when keyboard is visible

I got a pretty basic login form in my iOS application. The typical behavior I normally implement ist registering for the keyboard notifications and handling the scroll behavior of the UIScrollView in order to show the currently focused UITextField. However this time I need a slightly different behavior.

If the keyboard will show I want to scroll the scrollview so the submit button will be presented right above the keyboard and will be visible.

I know the recommended way is to use contentInsets but this seems to fail for me. I got it working with setting the contentOffset but I would love to see a better solution to this problem.

Here is my current code:

func keyboardWillShow(notification: Notification) {
    guard let userInfo: NSDictionary = notification.userInfo as NSDictionary?,
    let keyboardInfo = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else {
        return
    }
    let keyboardSize = keyboardInfo.cgRectValue.size

    guard let loginButton = loginButton else {
        return
    }
    let buttonOrigin: CGPoint = loginButton.convert(loginButton.bounds, to: self).origin
    let buttonHeight: CGFloat = loginButton.bounds.size.height
    var visibleRect = self.frame
    visibleRect.size.height -= keyboardSize.height

    if !visibleRect.contains(buttonOrigin) {
        let scrollPoint = CGPoint(x: 0.0, y: buttonOrigin.y - visibleRect.size.height + buttonHeight)
        scrollView.setContentOffset(scrollPoint, animated: true)
    }
}

Upvotes: 2

Views: 1247

Answers (1)

sundance
sundance

Reputation: 3040

Did you try it the following way?

func keyboardWillShow(notification: Notification) {
    self.scrollView.isScrollEnabled = true
    let contentInsets = UIEdgeInsetsMake(0.0, 0.0, self.keyboardSize.height, 0.0)
    self.scrollView.contentInset = contentInsets
    self.scrollView.scrollIndicatorInsets = contentInsets
    var rect = self.view.frame
    rect.size.height -= self.keyboardSize.height
    if !rect.contains(self.loginButton.frame.origin) {
        self.scrollView.scrollRectToVisible(self.loginButton.frame, animated: true)
    }
}

After hours of trying this is the way I do the scrolling in my applications.

Upvotes: 5

Related Questions