简体   繁体   中英

iOS UIView properties don't animate with CABasicAnimation

I can imagine a far amount of sighs when people see this question popup again . However, I have read through a lot of information both here, in the documentation and via Google and still haven't found a solution. So here goes nothing.

I'm trying to recreate the Facebook login screen, where the spacing and position animates with the keyboard to allow the user to still see all the input fields and login button.

This works when I use the kCAFillModeForwards and set removedOnCompletion to NO . But, as said in another thread here on SO, this seems to only visually change properties and the actual tap position isn't changed. So when the user is seemingly tapping an input field, iOS interprets it as a tap on the background.

So I tried setting the new position and size but when I do that the animation doesn't play, it just snaps to the new position. Putting it before the addAnimation call and after it, with and without transactions, it doesn't make any difference.

The delegate methods are still called, but you can't visually see any animation.

if([notification name] == UIKeyboardWillShowNotification) {

    CGRect currBounds = self.loginTable.tableHeaderView.layer.bounds;
    CGSize newSize = CGSizeMake(self.loginTable.tableHeaderView.bounds.size.width, 60);
    CGPoint newPos = CGPointMake(self.loginTable.layer.position.x, self.loginTable.layer.position.x - 50);


    //[CATransaction begin];
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
    [animation setToValue:[NSValue valueWithCGSize:newSize]];
    [animation setDelegate:self];

    [self.loginTable.tableHeaderView.layer addAnimation:animation forKey:@"headerShrinkAnimation"];


    CABasicAnimation *formPosAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    [formPosAnimation setToValue:[NSValue valueWithCGPoint:newPos]];
    [formPosAnimation setDelegate:self];        

    //formPosAnimation.removedOnCompletion = NO;
    //formPosAnimation.fillMode = kCAFillModeForwards;

    [self.loginTable.layer addAnimation:formPosAnimation forKey:@"tableMoveUpAnimation"];
    //[CATransaction commit];

    [self.loginTable.tableHeaderView.layer setBounds:CGRectMake(currBounds.origin.x, currBounds.origin.y, newSize.width, newSize.height)];
    [self.loginTable.layer setPosition:newPos];
}

I have found a way to make it work, can't say if it's the best way to do it but it seems to be working now.

The key thing was to combine almost everything. So I had to keep removedOnCompletion and fillMode on my animations while also updating the position in my animationDidStop method. It works without setting the two animation parameters as well, but you can see a small flicker in the end.

- (void)keyboardWillChange:(NSNotification *)notification {
newSize = CGSizeZero;
newPos = CGPointZero;

if([notification name] == UIKeyboardWillShowNotification) {
    newSize = CGSizeMake(self.loginTable.tableHeaderView.bounds.size.width, 60);
    newPos = CGPointMake(self.loginTable.layer.position.x, self.loginTable.layer.position.x - 50);
} else {
    newSize = CGSizeMake(self.loginTable.tableHeaderView.bounds.size.width, 150);
    newPos = CGPointMake(self.loginTable.layer.position.x, self.loginTable.layer.position.x + 50);
}

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"bounds.size"];
[animation setToValue:[NSValue valueWithCGSize:newSize]];
[animation setDelegate:self];

animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;

[self.loginTable.tableHeaderView.layer addAnimation:animation forKey:@"headerShrinkAnimation"];

/*-----------------------------*/

CABasicAnimation *formPosAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
[formPosAnimation setToValue:[NSValue valueWithCGPoint:newPos]];
[formPosAnimation setDelegate:self];        

formPosAnimation.removedOnCompletion = NO;
formPosAnimation.fillMode = kCAFillModeForwards;

[self.loginTable.layer addAnimation:formPosAnimation forKey:@"tableMoveUpAnimation"];

}

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
NSLog(@"Animation did stop");

CGRect currBounds = self.loginTable.tableHeaderView.layer.bounds;

[self.loginTable.tableHeaderView.layer setBounds:CGRectMake(currBounds.origin.x, currBounds.origin.y, newSize.width, newSize.height)];
[self.loginTable.layer setPosition:newPos];

[self.loginTable.tableHeaderView.layer removeAnimationForKey:@"headerShrinkAnimation"];
[self.loginTable.layer removeAnimationForKey:@"tableMoveUpAnimation"];

}

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