Animating multiple UIViews simultaneously - ios

I have three UIButton objects visually stacked one on top of another. When a user taps on a button the buttons below should move down a certain distance. I am using the following animation block:
// Assuming button 1 was clicked...
[UIView animateWithDuration:0.25f
delay:0.0f
options:UIViewAnimationOptionCurveLinear
animations:^(void) {
self.button2.frame = CGRectOffset(self.button2.frame, 0.0f, 20.0f);
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
If I increase the animation duration, e.g. from 0.25 to 0.75, the buttons do not remain together but they begin to move in different time intervals. I have tried with Core Animation methods, by grouping animations and other stuff, but haven't found any solution yet.
Do you have any ideas? Right now I'm keeping the duration in 0.25 until I come up with something.

One solution is to set both button2 and button3 as a subview in another UIView and animate the view instead of each of the buttons separately. Whether this is a good approach depends on what you are trying to accomplish with the stacked button.
EDIT:
Since my experience is that animations within a block are in sync, I implemented the code as show below. I tried numerous values for the animation duration (0.15, 0.25, 0.75, 1.25) and button2 and button3 are moving in sync (and since button2 is on top of button3, I can't actually see button3 at all, until I tap on button2, which causes button3 to move from underneath button 3).
- (IBAction)button1Tapped:(id)sender {
NSLog(#"button1Tapped...");
[UIView animateWithDuration:0.75f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^(void) {
self.button2.frame = CGRectOffset(self.button2.frame, 0.0f, 20.0f);
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
}
- (IBAction)button2Tapped:(id)sender {
NSLog(#"button2Tapped...");
[UIView animateWithDuration:0.75f
delay:0.0f
options:UIViewAnimationOptionCurveEaseOut
animations:^(void) {
self.button3.frame = CGRectOffset(self.button3.frame, 0.0f, 20.0f);
}
completion:^(BOOL finished) { NSLog(#"Finished"); }];
}
- (IBAction)button3Tapped:(id)sender {
NSLog(#"button3Tapped...");
}

Related

How to scale and change the origin of parent view and implement in subviews too?

I want to create a menu view which hides and unhides on button press. Now I managed to do it to the parent view but the buttons which are subview of the menuview are not scaling accordingly what i need to do? Here's the code!
menuInitFrame=menuView.frame;
newFrame=CGRectMake(320, 0, 0, 0);
Storing the initial state and new state;
if (menuView.hidden==NO) {
[UIView animateWithDuration:0.5
delay: 0.5
options: UIViewAnimationOptionCurveEaseIn
animations:^{
menuView.frame = newFrame; // move
}
completion:^(BOOL finished)
{
menuView.hidden=YES;
}];
}
else if(menuView.hidden==YES)
{
menuView.hidden=NO;
[UIView animateWithDuration:0.5
delay: 0.5
options: UIViewAnimationOptionCurveEaseIn
animations:^{
menuView.frame = menuInitFrame;
}
completion:^(BOOL finished)
{
//menuViewStatus=NO;
}];
}
Since you're using auto-layout you need to call layoutIfNeeded to recalculate frames of all subviews inside your menuView.
So inside your animation block add the following line:
menuView.frame = menuInitFrame;
[menuView layoutIfNeeded];

iOS how to animate view scaling from the center of the view?

I'm using an affine transform within a repeating/reversing animation to create a "pulsing" effect. However, I noticed that the button gets shifted right when the animation begins. The anchor point for the button is at (0.5,0.5):
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionRepeat|
UIViewAnimationOptionAutoreverse|
UIViewAnimationOptionAllowUserInteraction|
UIViewAnimationCurveEaseInOut
animations:^{
self.recordButton.transform = CGAffineTransformMakeScale(1.2, 1.2);
} completion:^(BOOL finished) {
}];
It appears that when the transform is applied, the origin of the button's frame stays at the same spot.
How can I animate scale transform so the center of the button remains in the same spot once the transform is applied?
I usually play with the frame and CGRect utility functions
[UIView animateWithDuration:0.5
delay:0
options:UIViewAnimationOptionRepeat|
UIViewAnimationOptionAutoreverse|
UIViewAnimationOptionAllowUserInteraction|
UIViewAnimationCurveEaseInOut
animations:^{
self.recordButton.frame = CGRectInset(self.recordButton.frame, -1.2, -1.2);
} completion:^(BOOL finished) {
}];

How to make UIView move by click?

I'm not sure whether I can describe it properly. It's a kind of UIView, and we see only it's part (with arrow,maybe. on the bottom of screen,maybe). User can click on it, and this view appears fullscreen(usually developer leaves there some additional information). How can I make it?
Try this:
-(void)show
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 568
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,0,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
-(void)hide
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,viewObj.frame.origin.y,viewObj.frame.size.width, viewObj.frame.size.height)];//Here "viewObj.frame.origin.y" means 0
[UIView animateWithDuration:0.5 animations:^
{
[viewObj setFrame:CGRectMake(viewObj.frame.origin.x,568,viewObj.frame.size.width, viewObj.frame.size.height)];
}
completion:^(BOOL finished)
{
}];
}
i just put the logic that just setting of view Y coordinate of That View and when user click on Button. that et animation and at the re setting the view frame with Y coordinate setting like:
yourview.frame = CGRectMake(0,280,320,568);
[UIView animateWithDuration:2
delay:0.1
options: UIViewAnimationOptionTransitionFlipFromBottom
animations:^{
yourview.frame = CGRectMake(0, 0, 320, 568);
}
completion:^(BOOL finished){
}];
Also see this example:
https://github.com/crocodella/PullableView
Here above github demo this same that you are looking for its output like:
Look at UIView reference:
https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
Specifically:
#property(nonatomic) CGPoint center
And
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
Example:
[UIView animateWithDuration:2.0 animations:^{
myView.center = CGPointMake(self.view.center.x, self.view.center.y + myOffset);
}];
Duration is in seconds. In this case, 2 seconds.
If you're using AutoLayout, you probably want to change the layout constant, rather then center property.
About Layout Constrains:
https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html
Look at constant property. You can also drag a constrain outlet from Interface Builder and access its constant. It's really simple once you get to know it a bit.

Correctly Using CGAffineTransformMakeScale

I have a UIButton laid out using storyboard. The button just contains an image. When the button is clicked, I want to animate the size of the button - decrease in size and then bring it back to the original size again.
I used the following code -
[UIView animateWithDuration:2.0 animations:^{
_favButton.transform = CGAffineTransformMakeScale(0.5, 0.5);
}completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 animations:^{
_favButton.transform = CGAffineTransformMakeScale(1, 1);
}];
}];
This code moves my button on the screen which I do not want. I want the center of the button to be fixed and the size be animated.
I have not used any Top Constraint in the storyboard for the button. How can I rectify this behaviour?
If you have auto layout turned on, you would need to turn it off.
But it doesn't seem to your problem here as per your description.
I would do the following to re-adjust to the center as it scales:
CGPoint cP = _favButton.center;
[UIView animateWithDuration:2.0 animations:^
{
_favButton.transform = CGAffineTransformMakeScale(0.5, 0.5);
_favButton.layer.position = cp;
}
completion:^(BOOL finished)
{
[UIView animateWithDuration:2.0 animations:^
{
_favButton.transform = CGAffineTransformMakeScale(1, 1);
_favButton.layer.position = cp;
}];
}];
Hope this helps.
SWIFT 3
button.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)

UILabel animated fade in out isn't working

I am trying to build an introduction to my app with UILabels fading in and out. I have two labels. I want the first one to fade in, stay on the screen for 4 seconds. Then second label should fade in and stay on the screen for 4 seconds. Then it should fade out both the labels.
I have the following code but it does not do anything since it goes straight to the final state. I have the following method in viewDidAppear(). What am I doing wrong?
-(void) animateLabels
{
[UIView beginAnimations:#"First Label Display" context:nil];
[UIView setAnimationDelay:4.0];
firstLabel.alpha = 1;
[UIView commitAnimations];
[UIView beginAnimations:#"Second Label Display" context:nil];
[UIView setAnimationDelay:6.0];
secondLabel.alpha = 1;
[UILabel commitAnimations];
[UIView beginAnimations:#"Hide Labels" context:nil];
[UIView setAnimationDelay:10.0];
secondLabel.alpha = 0;
firstLabel.alpha=0;
[UILabel commitAnimations];
}
Use block based animation & chain your animations together. So there are 3 steps. label1 fadesIn, Label2 fadesIn, finally Label3 fadesIn. I have written the code below for fading in label1 & label2. Fading out is simple. I think you can fill in the rest. Its straight-forward from here...
Try this -
[UIView animateWithDuration:1.0
delay:4
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^(void)
{
[firstLabel setAlpha:1.0];
}
completion:^(BOOL finished)
{
if(finished)
{
[UIView animateWithDuration:1.0
delay:4.0
options:UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction
animations:^(void)
{
[secondLabel setAlpha:1.0];
}
completion:^(BOOL finished)
{
if(finished)
{
//put another block her to hide both the labels.
}
}];
}
}];
I suggest rewriting this using blocks. First animateWithDuration:animations:completion: and then nested animateWithDuration:delay:options:animations:completion:. It's far more flexible, and there's no need to run on pre-blocks systems these days.
Also, your first animation as written wouldn't trigger for 4 seconds.
Here is a solution in swift 4+
UIView.animate(withDuration: 1.0, delay: 4, options: [.curveLinear, .allowUserInteraction], animations: {
firstLabel.alpha = 1.0
}) { finished in
if finished {
UIView.animate(withDuration: 1.0, delay: 4.0, options: [.curveLinear, .allowUserInteraction], animations: {
secondLabel.alpha = 1.0
}) { finished in
if finished {
//put another block her to hide both the labels.
}
}
}
}

Resources