Rotate a UIView on its X-axis(Horizontal axis) - iphone

I wanted to rotate a UIView on its horizontal axis for 360 degrees and then refresh the content in the view. I was looking out for solutions on this. Found a couple here n there. This is what I came out with.
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionTransitionNone animations:^{
self.tableView.layer.transform = CATransform3DMakeRotation(M_PI,1.0,0.0,0.0);
} completion:^(BOOL finished){
NSLog(#"Finished first pi");
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionTransitionNone animations:^{
self.tableView.layer.transform = CATransform3DMakeRotation(M_PI,1.0,0.0,0.0);
} completion:^(BOOL finished) {
NSLog(#"Finished second pi");
}];
}];
This flips the view but only by 180 degrees. I want it to flip one more time so that I can see the view normally..
Both my NSLogs are displayed one after the other. I am sure I am missing something here. ANy help would be helpful..
Thanks

In your completion block try concatenating the new transform with the current transform.
self.tableView.layer.transform = CATransform3DConcat(self.tableView.layer.transform, CATransform3DMakeRotation(M_PI,1.0,0.0,0.0));

You should check this answer How to make a CATransform3dMakeRotation rotate the other way? And chain together
I think that your problem is related with: "When you are working with a transform directly, Core Animation will interpolate the transform from the current value to the specified transform. It will find the shortest path to get to that transform, which will restrict the animation direction. If you try to animate the same transform property twice, the second value will simply override the first, not combine the two transforms together."

use this:-
rotatingView.layer.anchorPoint = CGPointMake(0.0f, 0.0f);
rotatingView.center = CGPointMake(0,
(rotatingView.center.y -
(rotatingView.bounds.size.height/2.0f)));
rotatingView.center = CGPointMake(0,
(rotatingView.center.y-
(rotatingView.bounds.size.height/2)));
// start the Page Open
[UIView beginAnimations:#"Animation" context:nil];
[UIView setAnimationDuration:13.0];
// set angle as per requirement
[rotatingView.layer setValue:[NSNumber numberWithInt:280]
forKeyPath:#"transform.rotation.x"];
[UIView commitAnimations];

You just have to change your code from 1.0 to 0.0 inside completion block and woohoo all done.
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionTransitionNone animations:^{
self.tableView.layer.transform = CATransform3DMakeRotation(M_PI,1.0,0.0,0.0);
} completion:^(BOOL finished){
NSLog(#"Finished first pi");
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionTransitionNone animations:^{
self.tableView.layer.transform = CATransform3DMakeRotation(M_PI,0.0,0.0,0.0);
} completion:^(BOOL finished) {
NSLog(#"Finished second pi");
}];
}];

You can also approach this using the .Repeat and .Autoreverse animation options + setting animation's repeat count. Here's an example in Swift:
UIView.animateWithDuration(time, delay: 0, options: [.Repeat, .Autoreverse], animations: {
UIView.setAnimationRepeatCount(3)
self.view.layer.transform = CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0)
}) { (completed) in
// completion
}

Related

UIButton always moves back to its first location?

I am having this hair pulling problem, i hope anybody will be able to help me out. it seems like a little thing but i have not been able to find any solution.
I have a UIButton that i want to move around with a animation block. Everytime i click the button i have it move to a new location, the button always moves to the correct location the problem is that it always moves from its first location to its new location.
lets say that i have a button at (0,0) i then move it to (0,50) works like a beaut!
Now i want to move the button to (0,100) and i expect it to animate from (0,50) to (0,100) but what it does it animate from (0,0) to (0,100) so it ends up in the right location, but moves FROM the wrong location.
i move the UIButton by setting a a new frame in a animation block
[UIView animateWithDuration:0.5f
delay:0.0f
options:UIViewAnimationCurveLinear
animations:^{
}
completion:nil];
in my case i move the button in a completion block when other controls a finished moving.
i really hope somebody out there knows exatly what im talking about and have the answer for me.
the code i use for animating the uibutton is this, the buttons name is "btnAddPhoneNumber" and its also the "sender"
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationCurveLinear
animations:^{
txtNewPhoneNumber.frame = CGRectMake(newXnumber, newYnumber, txtPhoneNumber.frame.size.width, txtPhoneNumber.frame.size.height);
}
completion:^(BOOL finished) {
txtNewPhoneNumber.placeholder = #"here you go!";
//animate add textfield button.
[UIView animateWithDuration:0.5f
delay:0
options:UIViewAnimationCurveLinear
animations:^{
[sender setFrame:CGRectMake(btnAddPhoneNumber.frame.origin.x, newYnumber, btnAddPhoneNumber.frame.size.width, btnAddPhoneNumber.frame.size.height)];
txtNewPhoneNumberTitle.frame = CGRectMake(newXtitle, newYtitle, txtPhoneNumberTitle.frame.size.width, txtPhoneNumberTitle.frame.size.height);
[btnDelete setFrame:btnDeleteRect];
}
completion:^(BOOL finished) {
}];
}];
thank you for reading my question, and for helping me find a solution.
EDIT (added code example)
Try adding UIViewAnimationOptionBeginFromCurrentState to the options of the second animation, see if it solves your problem.
[UIView animateWithDuration:0.5f
delay:0.0f
options:UIViewAnimationCurveLinear | UIViewAnimationOptionBeginFromCurrentState
animations:^{
}
completion:nil];
Another way to go would be to set the frame of the button again (to the same value) in the completion handler of the second animation.
Check this work around. As I mentioned in comments, you can use this as your last option. Not a recommended approach.
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationCurveLinear
animations:^{
txtNewPhoneNumber.frame = CGRectMake(newXnumber, newYnumber, txtPhoneNumber.frame.size.width, txtPhoneNumber.frame.size.height);
}
completion:^(BOOL finished) {
txtNewPhoneNumber.placeholder = #"here you go!";
[self performSelector:#selector(callSecondAnimation) withObject:nil afterDelay:1.5f)]; //or 0.5f
}];
- (void)callSecondAnimation {
//animate add textfield button.
[UIView animateWithDuration:0.5f
delay:0
options:UIViewAnimationCurveLinear
animations:^{
[sender setFrame:CGRectMake(btnAddPhoneNumber.frame.origin.x, newYnumber, btnAddPhoneNumber.frame.size.width, btnAddPhoneNumber.frame.size.height)];
txtNewPhoneNumberTitle.frame = CGRectMake(newXtitle, newYtitle, txtPhoneNumberTitle.frame.size.width, txtPhoneNumberTitle.frame.size.height);
[btnDelete setFrame:btnDeleteRect];
}
completion:^(BOOL finished) {
}];
}
Update:
Try this first,
[UIView animateWithDuration:1
delay:0
options:UIViewAnimationCurveLinear
animations:^{
txtNewPhoneNumber.frame = CGRectMake(newXnumber, newYnumber, txtPhoneNumber.frame.size.width, txtPhoneNumber.frame.size.height);
}
completion:^(BOOL finished) {
txtNewPhoneNumber.placeholder = #"here you go!";
txtNewPhoneNumber.frame = CGRectMake(newXnumber, newYnumber, txtPhoneNumber.frame.size.width, txtPhoneNumber.frame.size.height);//try setting it here once and then call next one
[self callSecondAnimation];
}];
- (void)callSecondAnimation {
//animate add textfield button.
[UIView animateWithDuration:0.5f
delay:0
options:UIViewAnimationCurveLinear
animations:^{
[sender setFrame:CGRectMake(btnAddPhoneNumber.frame.origin.x, newYnumber, btnAddPhoneNumber.frame.size.width, btnAddPhoneNumber.frame.size.height)];
txtNewPhoneNumberTitle.frame = CGRectMake(newXtitle, newYtitle, txtPhoneNumberTitle.frame.size.width, txtPhoneNumberTitle.frame.size.height);
[btnDelete setFrame:btnDeleteRect];
}
completion:^(BOOL finished) {
}];
}
I found the problem, the view used AutoLayout, when i removed the tick in AutoLayout the new position of my button is saved, and the next animation continues from the previously location.
thanks to ACB and Tobi for their input their helped me try different solutions that ended up fixing the problem!

iOS - Animation effects - Image pop-in

I'd like to have an image in my iphone app "pop-in" on screen rather than just appearing. By "pop-in" I mean that it would grow from a small dot to its actual size. For reference, this is exactly the same as the "pop" animation effect in Keynote.
I'm completely new to iOS animations, so if someone could point me in the direction on the animation effects I would need to use, it would be greatly appreciated.
Thanks
Brian
UPDATE
I've added this code from the suggestions below. This works but it scales my image down, rather than up. I know that is because I have 0.01 as the transform scale size, but I would like to know how I can start out with an image of size 0.0 and scale up to 1. Is it just a matter to setting the size of my image to 0?
Thanks
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 0.2];
image.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
The effect you’re looking for is something like this:
// instantaneously make the image view small (scaled to 1% of its actual size)
view.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
// animate it to the identity transform (100% scale)
view.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished){
// if you want to do something once the animation finishes, put it here
}];
if you want something like Facebook does on liking any post then use this
-(void)animateButton:(UIButton *)sender{
UIButton * btn = (UIButton *)sender;
[UIView animateWithDuration:0.3/1.5 animations:^{
btn.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.4, 1.4); // scales up the view of button
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
btn.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.7, 0.7);// scales down the view of button
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3/2 animations:^{
btn.transform = CGAffineTransformIdentity; // at the end sets the original identity of the button
}];
}];
}];}
just call this method when you want to animate the view
if you have text and image on the button and you just want to animate the image of the button then just replace "btn" with "btn.imageView" , this will just produce animation on the image view property of the button.
Hope it helps
All the best.
You have to animate the frame of the view, to shrink it from zero to the final state.
This can be done for example with UIView block animation.
So for example start with your view as an IBOutlet property self.myView with the final size and position, but set the hidden flag.
Then when you want it to appear use the following:
// Save old frame as final stater and set it to zero size for the start of the animation
// But keep the same center position, so it just grows and don't move around
CGRect oldFrame = self.myView.frame;
CGRect oldCenter = self.myView.center;
self.myView.frame = CGRectZero;
self.myView.center = oldCenter;
self.myView.hidden = NO;
NSTimeInterval duration = 0.3;
[UIView animateWithDuration:duration delay:0.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
// New position and size after the animation should be the same as in Interface Builder
self.myView.frame = oldFrame
}
completion:^(BOOL finished){
// You can do some stuff here after the animation finished
}];
Swift 2.0 version
view.transform = CGAffineTransformMakeScale(0.01, 0.01);
UIView.animateWithDuration(0.2, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
// animate it to the identity transform (100% scale)
self.view.transform = CGAffineTransformIdentity;
}) { (finished) -> Void in
// if you want to do something once the animation finishes, put it here
}
For that you will have to use a simple UIView
Add the UIview to your current view.
- (void) initPopUpView
{
popup.alpha = 0;
popup.frame = CGRectMake (160, 240, 0, 0);
[self.view addSubview:popup];
}
- (void) animatePopUpShow
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationWillStartSelector:#selector(initPopUpView)];
popup.alpha = 1;
popup.frame = CGRectMake (20, 40, 300, 400);
[UIView commitAnimations];
}

How to cancel UIView block-based animation?

I've searched loads of SO stuff and in Apple's references, but still unable to manage my problem.
What I have:
A screen with 2 UIImageViews and 2 UIButtons connected to them
2 kinds of animation:
Scaling up and then down of each image, one after another, only once in viewDidLoad
When a button pressed (a custom button hidden 'inside' of each UIImageView) it triggers animation of appropriate UIImageView–only one, not both–(also scale up, then down).
As I am writing for iOS4+ I'm told to use block based animations!
What I need:
How do I cancel a running animation? I've managed to cancel after all but the last one... :/
Here is my code snippet:
[UIImageView animateWithDuration:2.0
delay:0.1
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
isAnimating = YES;
self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 2.0, 2.0);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.bigLetter.transform = CGAffineTransformScale(self.bigLetter.transform, 0.5, 0.5);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 2.0, 2.0);
} completion:^(BOOL finished){
if(! finished) return;
[UIImageView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
self.smallLetter.transform = CGAffineTransformScale(self.smallLetter.transform, 0.5, 0.5);
}
completion:^(BOOL finished){
if (!finished) return;
//block letter buttons
[self.bigLetterButton setUserInteractionEnabled:YES];
[self.smallLetterButton setUserInteractionEnabled:YES];
//NSLog(#"vieDidLoad animations finished");
}];
}];
}];
}];
Somehow the smallLetter UIImageView is not working properly, because when pressed (through button) bigLetter is canceling animations properly...
EDIT:
I've used this solution, but still having problem with scaling down smallLetter UIImageView - not cancelling at all...
solution
EDIT2: I've added this at the beginning of next/prev methods:
- (void)stopAnimation:(UIImageView*)source {
[UIView animateWithDuration:0.01
delay:0.0
options:(UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionAllowUserInteraction)
animations:^ {
source.transform = CGAffineTransformIdentity;
}
completion:NULL
];
}
problem stays... :/ no idea how to interrupt last animation for letters in animation chain
You can stop all animations on a view by calling:
[view.layer removeAllAnimations];
(You'll need to import the QuartzCore framework to call methods on view.layer).
If you want to stop a specific animation, not all animations, your best best bet is to use CAAnimations explicitly rather than the UIView animation helper methods, then you will have more granular control and can stop animations explicitly by name.
The Apple Core Animation documentation can be found here:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreAnimation_guide/CreatingBasicAnimations/CreatingBasicAnimations.html
For iOS 10 use UIViewPropertyAnimator to animate.
It provides methods to start, stop and pause UIView animations.
let animator = UIViewPropertyAnimator(duration: 2.0, curve: .easeOut){
     self.view.alpha = 0.0
}
// Call this to start animation.
animator.startAnimation()
// Call this to stop animation.
animator.stopAnimation(true)
I'd add to Nick's answer that to make removeAllAnimations smooth next idea be very handy.
[view.layer removeAllAnimations];
[UIView transitionWithView:self.redView
duration:1.0f options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[view.layer displayIfNeeded];
} completion:nil];
You can try this (in Swift):
UIView.setAnimationsEnabled(false)
UIView.setAnimationsEnabled(true)
Note: you can put code between those two calls if necessary, for example:
UIView.setAnimationsEnabled(false)
aview.layer.removeAllAnimations() // remove layer based animations e.g. aview.layer.opacity
UIView.setAnimationsEnabled(true)

How to scale UIImageView properly with UIView animateWithDuration?

I'm scaling UIImageView and then reverting it using UIView animateWithDuration with UIViewAnimationOptionAutoreverse option. The problem is the image animation is a little bit jaggy (twitching) at the end of the animation. Here's my code:
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionAutoreverse
animations:^{
myImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);}
completion:^(BOOL finished){if (finished){
myImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0);}}];
I know that I'm missing something but don't know where to start :(
UPDATE1: I'm performing nested 6 animations where each next animation performs after previous one. For that I'm using block animations and performing each next animation in complete block.
UPDATE2: I have tried with UIViewAnimationOptionRepeat option but there's still some flash effect after each scale animation.
UIViewAnimationOptionAutoreverse does nothing without also using the UIViewAnimationOptionRepeat option. Your animation as written will shrink the image to 90%, then snap back to 100% in the completion block. Maybe you can follow this animation with another that scales back to 100% over a quarter second. Something like this:
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
myImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.9, 0.9);}
completion:^(BOOL finished){if (finished){
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut
animations:^{
myImage.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0);}
completion:NULL];}}];
.h file declerd.
NSInteger imgint;
.m file in code and try.
-(void)
{
[NSTimer scheduledTimerWithTimeInterval:(0.85f)target:self selector:#selector(play_btn_animation) userInfo:nil repeats:YES];
}
-(void)play_btn_animation
{
if(imgint == 0)
{
[UIView animateWithDuration:0.8
delay:0.0
options: UIViewAnimationOptionCurveEaseIn
animations:^{
img.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.8, 0.8);
}
completion:^(BOOL finished) {
img = 1;
}];
}
else
{
[UIView animateWithDuration:0.8
delay:0.0
options: UIViewAnimationOptionCurveEaseOut
animations:^{
img.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1);
}
completion:^(BOOL finished) {
imgint = 0;
}];
}
}

iPhone : UIVIew Boing kind of animation

Sorry for the poor title, I am trying to think of a easy way to explain this.
I have a UIView in the center of the screen which contains a progress indicator and background image.
What I want it to do is get bigger to a certain point and then shrink a tiny bit. So it "boings" in.
I had a play with normal UIView animations etc and have it coming in. However I thinking to get this to work well I need to use the views layer. The main issue at the moment is the indicator does not size.
Has anyone done a boing effect on a view?
Something like this?
- (void)boingView:(UIView *)theView {
[UIView animateWithDuration:0.1 animations:^(void) {
theView.transform = CGAffineTransformMakeScale(1.3, 1.3);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 animations:^(void) {
theView.transform = CGAffineTransformMakeScale(0.8, 0.8);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 animations:^(void) {
theView.transform = CGAffineTransformMakeScale(1.0, 1.0);
} completion:nil];
}];
}];
}