navigationBar and it's titleView rightBarButtonItem became smaller with animation - ios

At normal state UI is like follow
when tableview slide up, i want the navigationBar became small with animation.
Code like follow
CABasicAnimation *shake = [CABasicAnimation animationWithKeyPath:#"transform"];
shake.duration = DURATION_TIME;
shake.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0 ,1.0)];
shake.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 0.5, 1.0)];
shake.removedOnCompletion = NO;
shake.fillMode = kCAFillModeForwards;
[self.navigationController.navigationBar.layer addAnimation:shake forKey:#"shakeAnimation"];
after the animation UI like follow
I don't want the navigationBar's y position change. And the titleView and rightbarItem became flat, How to avoid them becomes flat?

Try the code below. It works before ios7
UIView * testView = self.navigationController.navigationBar ;
CGRect frame = testView.layer.frame ;
testView.layer.anchorPoint = CGPointMake(0.5f, 0.0f) ;
testView.layer.frame = frame ;
[UIView animateWithDuration:1.0 animations:^{
CABasicAnimation *shake = [CABasicAnimation animationWithKeyPath:#"transform"];
shake.duration = 1.0;
shake.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0 ,1.0)];
shake.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 0.5, 1.0)];
shake.removedOnCompletion = NO;
shake.fillMode = kCAFillModeForwards;
[testView.layer addAnimation:shake forKey:#"shakeAnimation"];
}];

Related

Animation resets to begin state after ending or firing second animation

I'm trying to make a breathing circle animation. Only breathInAnimation (grow circle) seems to animate. breathOutAnimation (shrink circle) gets called but doesn't seem to do anything. I'm guessing it immediately reverts back to the starting state but I don't understand why.
- (void)viewDidLoad
animationView = [[UIView alloc] initWithFrame:CGRectMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 2.0, 200, 200)];
animationView.backgroundColor = [UIColor blueColor];
animationView.layer.cornerRadius = 100;
animationView.center = self.view.center;
[self.view addSubview: animationView];
[self drawCircleEdge];
[self breathInAnimation];
[NSTimer timerWithTimeInterval:7.0 target:self selector:#selector(breathOutAnimation) userInfo:nil repeats:YES];
- (void)breathInAnimation
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
[scaleAnimation setValue:#"breathIn" forKey:#"id"];
scaleAnimation.duration = 4;
scaleAnimation.fromValue = [NSNumber numberWithFloat:0.1];
scaleAnimation.toValue = [NSNumber numberWithFloat:1];
[animationView.layer addAnimation:scaleAnimation forKey:#"scale"];
- (void)breathOutAnimation
CABasicAnimation *breathOut = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
breathOut.duration = 8;
breathOut.fromValue = [NSNumber numberWithFloat:1];
breathOut.toValue = [NSNumber numberWithFloat:0.1];
[animationView.layer removeAllAnimations];
[animationView.layer addAnimation: breathOut forKey:#"scale"];
I also tried using the delegate of scaleAnimation.
- (void)animationDidStop:(CABasicAnimation *)theAnimation2 finished:(BOOL)flag
This works but after the animation finished the circle goes back to the state it was after ending the first animation. Shrinking -> animation ends -> fullsize again.
I'm not sure what I'm missing here.
CAAnimations doesn't apply the transformation to your layer, it's animating on a presentation layer and then switch back to your layer when animation is finished.
You should apply your transform when you are playing the animation.
-(void)breathOutAnimation
{
CABasicAnimation *breathOut = [CABasicAnimation animationWithKeyPath:#"transform.scale"];
breathOut.duration = 8;
breathOut.fromValue = [NSNumber numberWithFloat:1];
breathOut.toValue = [NSNumber numberWithFloat:0.1];
[animationView.layer removeAllAnimations];
[animationView.layer addAnimation: breathOut forKey:#"scale"];
animationView.layer.transform = CATransform3DMakeScale(0.1, 0.1, 0.1);
}

Add a bounce effect to a flip animation

I animated a flip for a pie chart I have. Here is my code"
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
scaleAnimation.fromValue = [NSNumber numberWithFloat:1.0];
scaleAnimation.toValue = [NSNumber numberWithFloat:0.5];
scaleAnimation.duration = 1.0f;
scaleAnimation.removedOnCompletion = NO;
[self.pieChart addAnimation:scaleAnimation forKey:#"scale"];
animationDidStop:finished:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.scale.x"];
animation.fromValue = [NSNumber numberWithFloat:0.5];
animation.toValue = [NSNumber numberWithFloat:1.0];
animation.duration = 1.0f;
[self.pieChart addAnimation:animation forKey:#"scale"];
How can I add a bounce effect to the second animation? (The animation in animationDidStop:finished:)
Go with a CAKeyFrameAnimation instead of two CABasicAnimation:
CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.x"];
scaleAnimation.keyTimes = #[#(0), #(0.5), #(0.9), #(1)];
scaleAnimation.values = #[#(1.0), #(0.5), #(1.1), #(1.0)];
scaleAnimation.duration = 1.0f;
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
With keyTimes and values, you can specify multiple stances in your animation. Here, I made it start with a scale of 1, animating to a scale of 0.5 (your first animation values), then 1.1 (an overshoot to create a "bounce") and finally 1 (your second animation values). Tweak those to your liking!
If you want to do this animation in two parts, you can keep your first animation, then start a CAKeyFrameAnimation in the animationDidStop:finished: similar to this instead:
CAKeyframeAnimation *scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform.scale.x"];
scaleAnimation.keyTimes = #[#(0), #(0.8), #(1)];
scaleAnimation.values = #[#(0.5), #(1.1), #(1.0)];
scaleAnimation.duration = 1.0f;
scaleAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
If you instead want to use UIView animation blocks, you'll need to do something similar to this:
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.squareView.transform = CGAffineTransformMakeScale(0.5, 1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:1 delay:0 usingSpringWithDamping:0.6 initialSpringVelocity:0 options:0 animations:^{
self.squareView.transform = CGAffineTransformIdentity;
} completion:nil];
}];
You will probably want to play with the params to tweak the animation.

How to change the starting point or anchor point of animations using pop or CoreAnimation

The following code starts a scale animation and it expands along XY from the center of the UIButton. How to make it start from the left or frame.origin.x = 0
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds];
anim.fromValue = [NSValue valueWithCGRect:CGRectMake(signupButton.frame.origin.x,
signupButton.frame.origin.y,
0,
signupButton.frame.size.height)];
anim.toValue = [NSValue valueWithCGRect:signupButton.frame];
[anim setValue:#"progressBar" forKey:#"animName"];
anim.delegate = self;
// I tried to set anchor point but without any luck
// signupButton.layer.anchorPoint = CGPointMake(150, signupButton.frame.origin.y);
[signupButton.layer pop_addAnimation:anim forKey:#"signupButton"];
You are animating the bounds, but passing in the frame. You are correct in wanting to animate bounds.
So, I think this would be the correct code.
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds];
CGRect startRect = signupButton.layer.bounds;
startRect.size.width = 0.0;
anim.fromValue = [NSValue valueWithCGRect:startRect];
anim.toValue = [NSValue valueWithCGRect:signupButton.layer.bounds];
[anim setValue:#"progressBar" forKey:#"animName"];
anim.delegate = self;
//anchor on the center left
CGPoint center = signupButton.layer.position;
signupButton.layer.anchorPoint = CGPointMake(0, 0.5);
signupButton.layer.position = CGPointMake(center.x - signupButton.layer.bounds.size.width * 0.5, center.y);
[signupButton.layer pop_addAnimation:anim forKey:#"signupButton"];

how to continuous bouncing uibutton between two points

I'm new to iPhone developing,am using folling code to animate my UIButton it's animating perfectly but when i click the button the action not firing. plese help me out from this.
[UIButton animateWithDuration:3.0
delay:0.0f
options: UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionBeginFromCurrentState
animations: ^(void){
CGPoint p = Mybutton.center;
p.y += 100;
Mybutton.center = p;
}
completion:NULL];
Is this code in the button action or viewDidLoad? Try this one :
- (IBAction)buttonAnimation:(id)sender {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
animation.duration = .3;
animation.repeatCount = 5;
animation.fromValue = [NSValue valueWithCGPoint:yourButton.center];
animation.toValue = [NSValue valueWithCGPoint:CGPointMake(yourButton.center.x, yourButton.center.y-30)];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation.autoreverses = YES;
animation.removedOnCompletion = NO;
[yourButton.layer addAnimation:animation forKey:#"position"];}
You should put it in the button action.
Hope it helps

How can I replace CGAffineTransform scale and alpha animations using CABasicAnimations and Auto Layout?

As far as I can see, Apple wants us to move away from CGAffineTransform animations and into animations using:
myView.layoutConstraint.constant = someNewValue;
[myView layoutIfNeeded];
for animations that involve a translation of a view.
It also seems we should be now using CABasicAnimation animations for scale and rotation (and sometimes opacity) because it animates the view's layer and not the view and in doing so, plays nicely with auto layout.
I used the following code to apply an opacity and scale animation that worked beautifully:
[UIView animateWithDuration:0.1f animations:^{
// first animation
self.myMeButton.alpha = 1;
self.myMeButton.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2f animations:^{
// second animation
self.myButton.transform = CGAffineTransformMakeScale(1, 1);
}];
}];
Of course auto layout plays havoc with the scale animation and so I am trying to find an alternative way to do it. So far, I have come up with this:
[CATransaction begin]; {
[CATransaction setCompletionBlock:^{
// code for when animation completes
self.pickMeButton.alpha = 1;
CABasicAnimation *scaleDown = [CABasicAnimation animationWithKeyPath:#"scale"];
scaleDown.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
scaleDown.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)];
scaleDown.duration = 0.1;
[self.myButton.layer addAnimation:scaleDown forKey:nil];
}];
// describe animations:
CABasicAnimation* scaleUp = [CABasicAnimation animationWithKeyPath:#"scale"];
scaleUp.autoreverses = NO;
scaleUp.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)];
scaleUp.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
CABasicAnimation *fadeAnim = [CABasicAnimation animationWithKeyPath:#"opacity"];
fadeAnim.fromValue=[NSNumber numberWithDouble:0.0];
fadeAnim.toValue=[NSNumber numberWithDouble:1.0];
// Customization for all animations:
CAAnimationGroup *group = [CAAnimationGroup animation];
group.duration = 0.2f;
group.repeatCount = 1;
group.autoreverses = NO;
group.animations = #[scaleUp, fadeAnim];
// add animations to the view's layer:
[self.myButton.layer addAnimation:group forKey:#"allMyAnimations"];
} [CATransaction commit];
As you can see the code almost 3 times as long as before and the animation on the device is noticeably less 'smooth' than it was previously.
Is there any way to do this better?
Thanks in advance for your response.
EDIT: This seems to have done the trick in that the animations are smooth, but I still feel like the code for this could be a lot more succinct.
[UIView animateWithDuration:0.2f animations:^{
self.pickMeButton.alpha = 1;
CABasicAnimation* scaleUp = [CABasicAnimation animationWithKeyPath:#"transform"];
scaleUp.duration = 0.2;
scaleUp.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 1)];
scaleUp.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1)];
[self.pickMeButton.layer addAnimation:scaleUp forKey:nil];
}completion:^(BOOL finished) {
CABasicAnimation* scaleDown = [CABasicAnimation animationWithKeyPath:#"transform"];
scaleDown.duration = 0.1;
scaleDown.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.2, 1.2, 1)];
scaleDown.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)];
[self.pickMeButton.layer addAnimation:scaleDown forKey:nil];
}];
I don't know why you want to do it with CABasicAnimation for scale. You can do it like you mention at the top of your question. Set a new value for the view's width and height constraint constant values and then use [myView layoutIfNeeded] inside animateWithDuration. If the view doesn't have height and width constraints, but has constants to the top and bottom and/or left and right edges of the superview, change those values instead.

Resources