0
votes

I have a UIScrollView with a UIView inside based on an article how to use autolayout with input fields. The article explains how to set the UIView to equal height and with of the normal view, for more information: https://www.natashatherobot.com/ios-autolayout-scrollview/.

Now I have multiple UITextFields inside my content view. When I press a UITextField, I want my view to show the keyboard and scroll to the UITextField. At first, I tried an approach used by multiple, but the problem is, at the bottom of the screen, I get a lot of blank space from the bottom of the view which is unwanted. The approach I tried is using the following lines:

- (void)keyboardWillHide:(NSNotification *)notification {
    [[self scrollView] setContentInset:UIEdgeInsetsMake([[self scrollView] contentInset].top, 0.0f, 0.0f, 0.0f)];
}

- (void)keyboardWillShow:(NSNotification *)notification {
    [[self scrollView] setContentInset:UIEdgeInsetsMake([[self scrollView] contentInset].top, 0.0f, [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height, 0.0f)];
}

To change this, I thought changing the bottom to a more appropriate value would do the trick, but when I do this, the view won't scroll to the UITextField anymore when I press it. I can manually scroll the the field though. The way I achieved this, is using the following:

- (void)keyboardWillShow:(NSNotification *)notification {
    float keyboard = [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
    float offset = [[[[self contentView] subviews] lastObject] frame].size.height + [[[[self contentView] subviews] lastObject] frame].origin.y + 30.0f;

    if ([[self contentView] frame].size.height - [[[notification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height < offset) {
        [[self scrollView] setContentInset:UIEdgeInsetsMake([[self scrollView] contentInset].top, 0.0f, offset - ([[self view] frame].size.height - keyboard), 0.0f)];
    }
}

Does anyone know how I can ignore the blank space under the UITextFields when scrolling, but allow the scrollview to scroll to the selected UITextField. I tried using the method scrollRectToVisible, but this doesn't do anything.

1
Use github.com/michaeltyson/TPKeyboardAvoiding library, super easy. Just set TPKeyboardAvoidingScrollView as a Custom class of your scroll view, it will take care of all things you need to manage when keyboard is displayed.Bharat Modi
Thanks for the library, But is there a way to do it without including the library? I tried using the code, and the scrollview will scroll to the input field, but the scrollview jumps up and scrolls from the top when I use the code provided in the library.Sietse

1 Answers

0
votes

I've found the above answers have been outdated. Also not perfect when scroll.

Here's a swift version.

It will scroll right below the textField, no spare space. And It will restore to the way it was like its first appear.

//add observer
override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidShow(_:)), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ARVHttpPlayVC.keyboardDidHide(_:)), name: UIKeyboardDidHideNotification, object: nil)
}

func keyboardDidShow(notification: NSNotification) {
    let userInfo: NSDictionary = notification.userInfo!
    let keyboardSize = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)!.CGRectValue.size

    //calculate the space it needs to show the firstResponder textField completely
    var difference: CGFloat
    if inputTextField1.isFirstResponder() == true {
        difference = keyboardSize.height - (self.view.frame.height - inputTextField1.frame.origin.y - inputTextField1.frame.size.height)
    } else if inputTextField2.isFirstResponder() == true  {
        difference = keyboardSize.height - (self.view.frame.height - inputTextField2.frame.origin.y - inputTextField2.frame.size.height)
    } else {
        difference = keyboardSize.height - (self.view.frame.height - inputTextField3.frame.origin.y - inputTextField3.frame.size.height)
    }
    //if the textField frame under the keyboard, so scroll up to show it
    if difference > 0 {
        var contentInset:UIEdgeInsets = self.scrollView.contentInset
        contentInset.bottom = difference
        self.scrollView.contentInset = contentInset

        let scrollPoint = CGPointMake(0, difference)
        self.scrollView.setContentOffset(scrollPoint, animated: true)
    }

}

func keyboardDidHide(notification: NSNotification) {
    let contentInset:UIEdgeInsets = UIEdgeInsetsZero
    self.scrollView.contentInset = contentInset
}

//remove observer
deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
}