简体   繁体   中英

iOS - Subview not Animating with Frame Change

I have a view for which I'm trying to animate a height change when the keyboard slides up (code shown below). The view on which I'm calling the frame change is animating perfectly; however, That view contains a subview, which in turn contains a textfield (which is causing the keyboard to pop up), and these subviews are just jumping to their new locations instead of animating. I put auto layout constraints on the subview to constrain it to the left, bottom and right of the superview as well as maintain a constant height.

Example video here: http://youtu.be/EmcZ-cXeTbM

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slideViewForKeyboard:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(slideViewForKeyboard:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)slideViewForKeyboard:(NSNotification *)note {
    NSDictionary* userInfo = [note userInfo];

    // Get animation info from userInfo
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;    
    CGRect keyboardEndFrame;

    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];

    CGRect newFrame = CGRectMake(self.view.frame.origin.x,
                                 self.view.frame.origin.y,
                                 self.view.frame.size.width,
                                 keyboardEndFrame.origin.y);

    [UIView animateWithDuration:0 delay:0 options:(animationCurve << 16) animations:^{
        [self.view setFrame:newFrame];
    }completion:^(BOOL completed){}];
}
- (IBAction)endEditingOnTap:(UITapGestureRecognizer *)sender {
    [self.view endEditing:YES];
}

@end

You should be using animationDuration as the duration of your animation block.

Aside from that, you have another problem. Right now, you set the frame of your view inside the animation block, so the change is animated. But the system lays out the subviews later, during the layout phase of the run loop, outside your animation block. This means the subviews won't be animated to their new frames.

You can fix that by sending layoutIfNeeded to your view inside the animation block:

[UIView animateWithDuration:animationDuration delay:0 options:(animationCurve << 16) animations:^{
    self.view.frame = newFrame;
    [self.view layoutIfNeeded];
} completion:^(BOOL completed){}];

But you'll probably run into another problem. You're setting the frame of your view directly, but you're using auto layout. At some point, auto layout will probably set the frame back based on your constraints. You need to modify the constraints on your view to control its new frame, instead of setting the frame directly.

Set animation duration.

 [UIView animateWithDuration:0.3 delay:0 options:(animationCurve << 16) animations:^{
            [self.view setFrame:newFrame];
        }completion:^(BOOL completed){}];

You're passing in 0 to -[UIView animateWithDuration:delay:options:animations:completion] . This will not result in an animation because its going from frame 0 to frame n-1 (where n is the number of frames it would have generated) in 0 seconds, aka instantaneously. Try passing your animationDuration as the argument for duration that way it animates at the same speed as the keyboard

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM