Obj-c - Delayed animation when returning to original state?
Asked Answered
E

2

5

I'm using the below code to shift a view and my tableview up when my keyboard is activated. When the keyboard is closed however, it takes the upView a solid 2 seconds after the keyboard closes to return to where it was (the tableView on the other hand, is instant). Why is this happening?

      - (void)viewDidLoad {
            [super viewDidLoad];

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


        }

        - (void)keyboardWillChange:(NSNotification *)notification {


            NSDictionary* keyboardInfo = [notification userInfo];

            NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];

            CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];

            UITabBarController *tabBarController = [UITabBarController new];
            CGFloat tabBarHeight = tabBarController.tabBar.frame.size.height;


            self.keyboardHeight = keyboardFrameBeginRect.size.height - tabBarHeight;

        }


        - (void) animateTextView:(BOOL) up
         {

                const int movementDistance = self.keyboardHeight;

                const float movementDuration = 0.2f;
                int movement= movement = (up ? -movementDistance : movementDistance);


                [UIView beginAnimations: @"anim" context: nil];
                [UIView setAnimationBeginsFromCurrentState: YES];
                [UIView setAnimationDuration: movementDuration];

                self.upView.frame = CGRectOffset(self.upView.frame, 0, movement);
                [UIView setAnimationDidStopSelector:@selector(afterAnimationStops)];
                [UIView commitAnimations];

                self.tableView.frame = CGRectOffset(self.tableView.frame, 0, movement);
                [UIView setAnimationDidStopSelector:@selector(afterAnimationStops)];
                [UIView commitAnimations];

        }

    - (void)textViewDidBeginEditing:(UITextView *)textView
    {

     [self animateTextView:YES];

    }

- (void)textViewDidEndEditing:(UITextView *)textView
{
    [self animateTextView:NO];
}

UPDATED CODE

.m

- (void)handleKeyboard:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval duration = 3;
    [value getValue:&duration];
    if (aNotification.name == UIKeyboardWillHideNotification) {
        /** KEYBOARD HIDE **/

       [UIView animateWithDuration:0 animations:^{ self.upView.frame = CGRectOffset(self.upView.frame, 0, self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, self.keyboardHeight); } completion:^(BOOL finished) {}];


        [self moveCustomView:NO duration:duration];
        NSLog(@"CLOSED!");
    }

    if (aNotification.name == UIKeyboardWillShowNotification) {
        /** KEYBOARD SHOW **/

 [UIView animateWithDuration:0 animations:^{ self.upView.frame = CGRectOffset(self.upView.frame, 0, -self.keyboardHeight); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, -self.keyboardHeight); } completion:^(BOOL finished) {}];


        [self moveCustomView:YES duration:duration];
    }
}

- (void)moveCustomView:(BOOL)move duration:(NSTimeInterval)time{

}
Eleaseeleatic answered 29/1, 2018 at 18:38 Comment(9)
Are you (somewhere) also registering for the UIKeyboardWillHideNotification?Dipstick
@Dipstick See edited code above - I'm using keyboardWillChange but no, not willHideNotification.Eleaseeleatic
OK - you want to add a function to handle "keyboard will hide" - then essentially do the reverse of what you're doing for "keyboard will show". Lots and lots of examples out there.Dipstick
can you post the code where animateTextView is called?Tieck
@Eleaseeleatic - start with Apple's docs: developer.apple.com/library/content/documentation/…Dipstick
@Dipstick Ok, so why does adding keyboardWillHide keep my upView from delaying? Just trying to connect the dots lolEleaseeleatic
@Eleaseeleatic - well, you currently don't show where you're calling animateTextView() so it's a little tough to say exactly what's going on. The standard method is to register for both show and hide keyboard notifications, and then adjust your layout accordingly.Dipstick
@Dipstick see animateTextView in edit aboveEleaseeleatic
@Eleaseeleatic the doc says, use of commitAnimations is discouraged in iOS 4 and later, have you tried using animateWithDuration ? [UIView animateWithDuration:movementDuration animations:^{ self.upView.frame = CGRectOffset(self.upView.frame, 0, movement); self.tableView.frame = CGRectOffset(self.tableView.frame, 0, movement); } completion:^(BOOL finished) {}]Tieck
I
5

This issue might be with the animation duration, so you can get the keyboard showing and hiding animation duration from the -(void)handleKeyboard:(NSNotification *)notification {}

and also handle the showing and hiding your custom view inside the same function. Add the following code to your viewDidLoad function

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

Handle keyboard actions and UI changes

- (void)handleKeyboard:(NSNotification*)aNotification{
    NSDictionary* info = [aNotification userInfo];
    NSValue* value = [info objectForKey:UIKeyboardAnimationDurationUserInfoKey];
    NSTimeInterval duration = 0;
    [value getValue:&duration];
    if (aNotification.name == UIKeyboardWillHideNotification) {
        /** KEYBOARD HIDE **/

        //calculate your view frames and handle UI changes
        /*
         .
         .
         .
         .
         .
         */
        [self moveCustomView:NO duration:duration];
    }

    if (aNotification.name == UIKeyboardWillShowNotification) {
        /** KEYBOARD SHOW **/

        //calculate your view frames and handle UI changes
        /*
         .
         .
         .
         .
         .
         */
        [self moveCustomView:YES duration:duration];
    }
}

- (void)moveCustomView:(BOOL)move duration:(NSTimeInterval)time{

}
Igloo answered 5/2, 2018 at 8:54 Comment(4)
This works seamlessly, with one exception: For some reason when I hide my keyboard, it executes keyboardWillHideNotification twice? I placed a log inside of keyboardWillHide, and the console shows it twice (in other words, my uiview moves down further than necessary?) I've skimmed my code for potential duplicates, and nothing else is present :/Eleaseeleatic
@Eleaseeleatic Please check how many time you have been added UIKeyboardWillHideNotification notification?Igloo
I only have it once - that said, I do have keyboardWillChange notification in order to grab the height of the keyboard in my viewDidLoad - would that be affecting it? I'd assume not, as it doesn't "show" twice?Eleaseeleatic
@Eleaseeleatic Yes, that would be the problem, you can use only UIKeyboardWillHideNotification and UIKeyboardWillShowNotification, using these two observers it is very easy to handle keyboard and other UI frame changes.Igloo
T
1

I think you need to use thread to call animation immediately...

- (void)textViewDidBeginEditing:(UITextView *)textView {

    dispatch_async(dispatch_get_main_queue(), ^{
        [self animateTextView:YES];
    });
}

- (void)textViewDidEndEditing:(UITextView *)textView {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self animateTextView:NO];
    });
}

I'm not much aware of your problem, but try this because if we got this type of problems dispatch_async() will solve.

Teleran answered 10/2, 2018 at 6:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.