leticia r
leticia r

Reputation: 11

Textfield inside a scroll view only moves up after keyboard appears IOS

I have the following problem: I have a scrollView that has a textField inside it. I need that when i tap on the textField the keyboard shows up and textField (inside the scroll) moves up immediately (at the same time) when the keyboard shows up. Right now textField appears but with a delay, like a few milliseconds after keyboard shows, like this:

click here to see the problem

UPDATE:

I've overrode the methods for keyboard handling like this:

override func keyboardWillShow(_ notification: Notification!) {
    guard let userInfo = notification.userInfo, let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
        return
    }

    // this constraint -> viewContainerButtonBottomConstraint 
    //refers to the button that must have above the keyboard 
    //when keyboard shows up.   
    self.viewContainerButtonBottomConstraint.constant = frame.height
    UIView.animate(withDuration: 0.3, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)

    let contentInset = UIEdgeInsets(top: 0, left: 0, bottom: frame.height, right: 0)
    scrollView.contentInset = contentInset
    
    if #available(iOS 11.0, *) {
        self.viewContainerButtonBottomConstraint.constant -= self.view.safeAreaInsets.bottom
    }
}

override func keyboardWillHide(_ notification: Notification!) {
    scrollView.contentInset = UIEdgeInsets.zero
    
    self.viewContainerButtonBottomConstraint.constant = 0
    
    UIView.animate(withDuration: 1, animations: {
        self.view.layoutIfNeeded()
    }, completion: nil)
} 

The Registration of observers are made in a parent class:

- (void)addNotificationKeyboard {
    if (kKeyboardNotificationsShowAvailable) {
     [[NSNotificationCenter defaultCenter] addObserver:self
                                           
     selector:@selector(keyboardWillShowNotification:)
                                                 
     name:UIKeyboardWillShowNotification
                                               object:nil];
   }
   if (kKeyboardNotificationsHideAvailable) {
     [[NSNotificationCenter defaultCenter] addObserver:self
                                             
     selector:@selector(keyboardWillHideNotification:)
                                                 
     name:UIKeyboardWillHideNotification
                                               object:nil];
}

}

And methods keyboardWillShowNotification and keyboardWillHideNotification are also in parent class, they are override like I showed above:

- (void)keyboardWillShowNotification:(NSNotification*)notification
{
   NSDictionary* keyboardInfo = [notification userInfo];
   NSValue* keyboardFrameBegin = [keyboardInfo 
   valueForKey:UIKeyboardFrameEndUserInfoKey];
   self.keyboardHeight = [keyboardFrameBegin CGRectValue].size.height;
}

- (void)keyboardWillHideNotification:(NSNotification*)notification
{
    if (self.view.frame.origin.y != 0) {
    if (self.tabBarController) {
        if (!(self.view.frame.origin.y == 64))
            [UIUtilities moveView:self.view newYposition:-64];
    }
    else
        [UIUtilities moveView:self.view newYposition:0];
    }
    [self.view endEditing:YES];
}

Thanks in advance for the answer!

Upvotes: 1

Views: 210

Answers (2)

Yuma Technical Inc.
Yuma Technical Inc.

Reputation: 723

This is what I have:

@objc func adjustForKeyboard(notification: Notification)
{
    let userInfo = notification.userInfo!
    let keyboardScreenEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)

    if notification.name == Notification.Name.UIKeyboardWillHide
    {
        self.scrollForm.contentInset = UIEdgeInsets.zero
    }
    else
    {
        self.scrollForm.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardViewEndFrame.height, right: 0)
    }
    self.scrollForm.scrollIndicatorInsets = self.scrollForm.contentInset
    //let selectedRange = self.scrollForm.selectedRange
    //self.scrollForm.scrollRangeToVisible(selectedRange)
}

And within the viewDidLoad():

    let notificationCenter = NotificationCenter.default
    notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: Notification.Name.UIKeyboardWillHide, object: nil)
    notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: Notification.Name.UIKeyboardWillChangeFrame, object: nil)

This is probably similar to what you have, try replace your overrides with the above.

Upvotes: 0

drekka
drekka

Reputation: 21893

What you want is not hard to do. There is a system notification called UIKeyboardWillShow that is sent before a keyboard is displayed. Watch for that. It's user info contains all the information about the size and position that the keyboard will be when it's on screen, and the animation that will be used to get it there. All you have to do then is immediately fire off a matching animation to move or adjust your display. Both animations will then run at the same time.

Upvotes: 0

Related Questions