How do I animate the move a UILabel with auto layout constraints? - ios

I'm trying to move a UILabel to the left and animate the movement. The UILabel is created from a storyboard, and has the following constraints:
But if I try to make the trailing space constant equal to say, 150 instead of 20 to move it to the left, it bounces to the left weirdly for a second then comes back to the middle. So I lowered the priority of the left leading constraint to 900, but the same thing still happened.
So I tried:
self.textToReadLabel.transform = CGAffineTransformMakeTranslation(-500.0, 0.0);
Which moves it, but if I use an animation with it it slides off screen, slides back on and then rests in the place it should... after all those theatrics.
How exactly would I achieve this?
Entirety of what happens when I tap the button to move the label:
self.textHorizontalPlacementConstraint.constant = 150.0;
self.textHorizontalPlacementConstraint2.constant = -110.0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
CATransition *animation = [CATransition animation];
animation.duration = 0.5;
animation.type = kCATransitionFade;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.textToReadLabel.layer addAnimation:animation forKey:#"changeTextTransition"];
// Change the text
self.textToReadLabel.text = #"text";
}

To get a layout change animated you need to change the constant in your NSLayoutConstraint and then call:
self.textHorizontalPlacementConstraint.constant = 150.0;
self.textHorizontalPlacementConstraint2.constant = -110.0;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
Also make sure you're constraints are consistent. So if you increase the trailingSpace also reduce the leadingSpace.

Related

How to reduce the opacity of an UIButton gradually?

In my project i have an UIButton which on clicking zooms. Everything is fine till here but i require the opacity of the button to gradually decrease from 1 to 0. I mean it should decrease in 1,0.9,0.8,0.7,0.6,0.5,0.4,0.3,0.2,0.1,0.0 sequence. My current code is
-(void)roundButtonAnimation
{
self.buttonZoom = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
self.buttonZoom.duration = 0.8f;
self.buttonZoom.values = #[[NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(2,2,2)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(3,3,3)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(5,5,5)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(6,6,6)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(7,7,7)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(9,9,9)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(10,10,10)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(11,11,11)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(12,12,12)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(13,13,13)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(14,14,14)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(15,15,15)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(16,16,16)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(17,17,17)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(18,18,18)],[NSValue valueWithCATransform3D:CATransform3DMakeScale(50,50,50)]];
self.buttonZoom.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
self.roundButton.transform = CGAffineTransformMakeScale(0,0);
self.roundButton.alpha = 0.3;
[self.roundButton.layer addAnimation:self.buttonZoom forKey:#"buttonScale"];
[self.CLSpinnerView1 stopAnimating];
//[self performSelector:#selector(secondView) withObject:self afterDelay:0.3];
[self performSelector:#selector(postNotification) withObject:self afterDelay:0.6];
}
[UIView animateWithDuration:1.0
delay:0.0
options: UIViewAnimationCurveLinear
animations:^{
self.roundButton.transform = CGAffineTransformMakeScale(50.0f, 50.0f);
self.roundButton.alpha = 0.0;
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
Let's explain a little, in this animation block you say that the animation should take place in one second, during this second based on a linear curve (thus always equal increment/decrement) the button should zoom 50 times and alpha should be animate to 0.
I do not understand why you are using a more complicated CAKeyframeAnimation over that simple animation block.
Keyframe animation are useful when you want more power over timings and animate over a set of values.
UIView animateWithDuration:animations: should serve your purpose here.
[UIView animateWithDuration:1.0 animations:^{
button.alpha = 0.0;
}];
Will gradually change the button's alpha to 0 over one second (...WithDuration:1.0...).
See the The UIView Class Reference for more information.
Hope this helps.
Try this
[button.layer removeAnimationForKey:#"opacity"];

How to flip the view vertically on another view iOS?

I'm developing an app which contained stack of views and i want that when the user swipes down on a image view this flip and shows another view.Its working but while its flipping vertically it merging with below lying view and showing another view.
Please go through the link , one will comes to know:https://dribbble.com/shots/1667024-Events-deck-animation
In above link,in animation after swipe left and right ,the user will down vertically without merging with below lying views.Please any help how to implement this vertical flip animation as shown in the mentioned link.
I am using the following code to flip veertically for single layer:
float duration = 1.0f;
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.x"];
animation.delegate = self;
animation.fromValue = [NSNumber numberWithDouble:-0.0f * M_PI];
animation.toValue = [NSNumber numberWithDouble:-1.0f * M_PI];
animation.duration = duration;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeRemoved;
animation.repeatCount =1;
animation.beginTime = CACurrentMediaTime();
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[photo.layer addAnimation:animation forKey:#"rotationX"];
photo.layer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
Please any one knowsshare it ,I need to implement this animation.
Try using UiView's transitionFromView method with UIViewAnimationOptionTransitionFlipFromBottom or UIViewAnimationOptionTransitionFlipFromTop for implementing animations on UIView than view's layer.
Like:
[UIView transitionFromView:viewToReplace
toView:replacementView
duration:1
options:UIViewAnimationOptionTransitionFlipFromTop
completion:nil];
Add this call in the swipe gesture selector method of the viewToReplace
For more see this link: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/doc/uid/TP40006816-CH3-SW105
EDIT:
May be This will work for you.
// Consider flipView as the view that need to flip vertical
[UIView transitionWithView:flipView
duration:1
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^{
// flipView.backgroundColor = [UIColor greenColor];
// update to be done with flip
} completion:nil];
Just try to comment the last line in your code and your view will animate or flip vertically on the same place without merging with the underlying views.

Animating UIView frame with constraints

I have an element in a UIView with a constraint that says it should always be 10 pixels from the bottom of the view. I am then attempting to animate this view's height so that it appears to slide down the screen. According to the constraint, the element should always be 10 pixels from the bottom of the view. This holds true when I add the view like so...
printView *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"printView"];
[self addChildViewController:vc];
vc.view.frame = CGRectMake(0, 60, vc.view.frame.size.width, HEIGHT);
vc.view.layer.masksToBounds = FALSE;
[vc.view.layer setShadowOffset:CGSizeMake(0.0, 5.0)];
[vc.view.layer setShadowOpacity:0.8];
vc.view.layer.shadowColor = [[UIColor blackColor] CGColor];
vc.view.layer.shadowRadius = 8;
vc.view.clipsToBounds = TRUE;
[self.view insertSubview:vc.view aboveSubview:docWebView];
I can change HEIGHT to whatever I want and the element is always 10 pixels from the bottom of the view. The problem comes when I try to animate the height
printView *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"printView"];
[self addChildViewController:vc];
vc.view.frame = CGRectMake(0, 60, vc.view.frame.size.width, 0);
vc.view.layer.masksToBounds = FALSE;
[vc.view.layer setShadowOffset:CGSizeMake(0.0, 5.0)];
[vc.view.layer setShadowOpacity:0.8];
vc.view.layer.shadowColor = [[UIColor blackColor] CGColor];
vc.view.layer.shadowRadius = 8;
vc.view.clipsToBounds = TRUE;
[self.view insertSubview:vc.view aboveSubview:docWebView];
[UIView animateWithDuration:5.0 animations:^{
vc.view.frame = CGRectMake(0, 60, vc.view.frame.size.width, 200);
[self.view setNeedsDisplay];
}];
The constraint is no longer honored and instead of the view sliding in with the element always 10 pixels from the bottom, it looks like the element is being uncovered because the element does not move with the view. I hope I am explaining this well enough. To put it another way, I'm going for the effect of a map being pulled down, but instead it looks like the map is already there and a piece of paper that is covering it is being pulled away. Thanks for your help.
When using constraints, you shouldn't be setting frames, you should be adjusting the constraints. When you initially set up your constraints, you should make an IBOutlet to the height constraint, and then animate its constant parameter in the animation block. If you had a height constraint called heightCon, you could do this:
[UIView animateWithDuration:5.0 animations:^{
self.heightCon.constant = 200
[self.view layoutIfNeeded];
}];
I'm not sure about your structure, that self.view might have to be vc.view instead.
After Edit:
This is the way to animate a height constraint, but I'm not sure that's what you want to do to accomplish the look you're after. I'm not really sure what to make of your last paragraph. If you're going for an effect of a map being pulled down, it seems like the bottom constraint needs to be either animated or eliminated.

How do I take a UIView with a background pattern set and shrink it down vertically with an animation

I want the top of the view to meet the bottom of the view in a quick animation for its disappearance. (Preferably have it grow for a second first.)
How would I go about doing this? The UIView has a background pattern set with [UIColor colorWithPattern:], and when I do self.textOptionsPopover.transform = CGAffineTransformMakeScale(0.0, 0.5);, it just disappears completely.
You have wrong x scale parameter - CGAffineTransformMakeScale(0.0, 0.5)
Change to CGAffineTransformMakeScale(1.0, 0.5), cause you don't want to modify your width.
0.0 is the reason that your view is disappearing.
But if you prefer to make it growing for a while first, it would be easier to use CAKeyframeAnimation - you can easly control key-times, values and timing functions. For example you can do something like this:
CAKeyframeAnimation *shrinkAnimation = [CAKeyframeAnimation animationWithKeyPath:#"transform"];
shrinkAnimation.values = [NSArray arrayWithObjects:
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.4, 1.0)],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 0.0, 1.0)],
nil];
shrinkAnimation.keyTimes = [NSArray arrayWithObjects:#0.0, #0.2, #1.0, nil];
shrinkAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
shrinkAnimation.duration = 0.4;
shrinkAnimation.removedOnCompletion = NO;
shrinkAnimation.fillMode = kCAFillModeForwards;
[self. textOptionsPopover.layer addAnimation:shrinkAnimation forKey:#"shrink"];
Edited:
If you want the view to shrink "from top to bottom", just change the anchor point of the layer (remember that changing anchor point will change the frame!):
CGRect frame = self.textOptionsPopover.layer.frame;
self.textOptionsPopover.layer.anchorPoint = CGPointMake(0.5, 1.0);
self.textOptionsPopover.layer.frame = frame;
You could change the frame size and animate that.
For example
Suppose finalFrameSize is a CGRect for the final value, you could get the animation effect like this.
[UIView animateWithDuration:0.3f
animations:^{
currentView.frame = finalFrameSize;
}
completion:^(BOOL finished){
// Do something after the animation is comlete
}];

UITextField being clipped during CABasicAnimation with keyPath of bounds.size.width

I have a somewhat of an odd issue on hand. I have UITextField. This TextField has it’s width resized when a button is tapped. To do that I first did the following:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
[UIView beginAnimations:nil context:nil];
self.textField2.bounds = newbounds;
[UIView commitAnimations];
Easy enough and it worked. Now I move along and try to exert a bit more control over the animation. To do that I go the next level up to CABasicAnimation using the following:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
CABasicAnimation *animShrink = [CABasicAnimation animation];
animShrink.keyPath = #"bounds";
animShrink.toValue = [NSValue valueWithCGRect:newbounds];
animShrink.duration = 0.5;
animShrink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animShrink.delegate = self;
[self.textField2.layer addAnimation:animShrink forKey:#"shrink"];
And that is when I run into the clipping issue during the animation as can be seen at: http://coldstorage.macbonsai.com/public/cabasic_animation_clipping.png (since I “need at least 10 reputation to post images” as per Stackoverflow).
So I tried the following version of the animation:
CGRect newbounds = originalBounds;
newbounds.size.width = newbounds.size.width/2;
CABasicAnimation *animShrink = [CABasicAnimation animation];
animShrink.keyPath = #"bounds.size.width";
animShrink.fromValue = [NSNumber numberWithFloat:originalBounds.size.width];
animShrink.toValue = [NSNumber numberWithFloat:newbounds.size.width];
animShrink.duration = 0.5;
animShrink.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animShrink.delegate = self;
[self.textField2.layer addAnimation:animShrink forKey:#"shrink"];
Still encountered the same issue. At this point I removed all constraints from the UITextField and tried both the CABasicAnimation versions. Same issue. At this point I don’t know what else to do. Any help will be greatly appreciated.
Many thanks in advance.
If you change the style of the button to UITextBorderStyleNone it doesn't get clipped.
My guess is that when the style is UITextBorderStyleRoundedRect, Apple probably just adds a UIImageView to the button with the "round rect" image, so when you animate the button's layer, its subviews don't animate together, because in iOS you have to explicitly animate all sublayers.

Resources