UIView will only animate once - ios

I'm trying to animate an arrow spinning while my app downloads information. After each half spin, I want the app to check if the data has been downloaded yet. If not, the arrow should spin halfway again, with a short pause in between each spin.
-(void)animation {
[UIView animateWithDuration:0.7 delay:0 options:0 animations: ^{
imageView.transform = CGAffineTransformMakeRotation(180 * M_PI / 180);
} completion: ^(BOOL completed) {
if (completed && stillReloading) {
[self performSelector:#selector(animation) withObject:nil afterDelay:0.2];
}
}];
}
Even though the animation function is continually called, the image only rotates once. All calls made to the animation function after the first animation are ignored. Why is this? I don't want to set the repeat option on the animation as I do not know how many times the arrow will have the spin, and as I would like there to be a short pause between each spin.

This line
imageView.transform = CGAffineTransformMakeRotation(180 * M_PI / 180);
sets the angle to 180 degrees, and just that. The next time it's called same angle is used, so you see no animation.

If you want to rotate it again from its current position then you need to use a different method. CGAffineTransformMakeRotation makes a rotation from the identity transform. So what you end up with is this: Rotate to 180 degrees, rotate to 180 degrees, rotate to 180 degrees and the object never moves. Instead you need to use a method that applies the offset to the current transform. That is what the following method is for:
CGAffineTransformRotate(CGAffineTransform, CGFloat)
However, instead of applying it to CGAffineTransformIdentity as Saohooou's answer does, you should apply it to the current transform of your view.

Because you've made you view animate to angle (180 * M_PI / 180), it will never spring again if you set the same angle to it.
try this
CGFloat t = 180*M_PI / 180.0;
CGAffineTransform translateSpring = CGAffineTransformRotate(CGAffineTransformIdentity, t);
[UIView animateWithDuration:0.7 delay:0.0 options:nil animations:^{
imageView.transform = translateSpring;
} completion:^(BOOL completed) {
if (completed && stillReloading) {
//Use this method to let it spring back to its original angle
[UIView animateWithDuration:0.07 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
imageView.transform = CGAffineTransformIdentity;
} completion:NULL];
[self performSelector:#selector(animation) withObject:nil afterDelay:0.2];
}
}];
OR you can also set a dynamically update angle for your imageView to tranform into. See if it could help:)
Base on your problem, you can see my code, Here I use an animation to change the view back to its identity Transformation:
if (completed && stillReloading) {
//Use this method to let it spring back to its original angle
[UIView animateWithDuration:0.07 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
imageView.transform = CGAffineTransformIdentity;
} completion:NULL];
[self performSelector:#selector(animation) withObject:nil afterDelay:0.2];
}
// So if you want to transform it without getting seen, you can simply detele the animation code
if (completed && stillReloading) {
imageView.transform = CGAffineTransformIdentity;
[self performSelector:#selector(animation) withObject:nil afterDelay:0.2];
}

You will find that it is very difficult to get the arrow to rotate continuously clockwise in 180 degree increments. It will be simpler to rotate it in 90 degree increments.
You need to apply new rotation to the arrow's existing transform, to add more rotation each time.
-(void)animateArrowRotation {
[UIView animateWithDuration:0.35 delay:0 options:0 animations: ^{
imageView.transform = CGAffineTransformRotate(imageView.transform, M_PI_2);
} completion: ^(BOOL completed) {
if (completed && stillReloading) {
[self animateArrowRotation];
}
}];
}

Related

Rotating Image multiple times and stopping at desired degree?

i had tried various method and couldn't figure out how to achieve this.i searched on internet a lot but can't figure out.
i have an ImageView (a wheel which spins) , i want to rotate it by 360 degree for 10 times(this is to just give user feel of fast turning wheel) , and then i want to rotate it by particular value say 90 degree( but it might be varying).
after this animation finishes i want to bring ImageView back to the initial position.
how do i achieve this ?
Thanks in advance.
well i found out how to do this.
i used below method to rotate by 360 degree for 10 times , and then rotate by particular degree.
-(void)rotate:(int)degreeToRotate
{
CGFloat radians = (M_PI/180) * degreeToRotate;
[UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations: ^{
//configuring to rotate 360 degree 10 times
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 ];
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 10;
[_scoreImageView.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
} completion:^(BOOL finished) {
//rotate by particular degree
[ UIView animateWithDuration:2 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// -radians, to ensure clockwise rotation
self.scoreImageView.transform = CGAffineTransformMakeRotation(-radians);
} completion:^(BOOL finished) {
//method call to reset image original position
[self performSelector:#selector(resetPosition) withObject:nil afterDelay:3];
}];
}];
}
below method is used to reset image to original position.
-(void)resetPosition
{
[UIView animateWithDuration:0.2 animations:^() {
self.scoreImageView.transform = CGAffineTransformIdentity;
}];
}

UIImageview rotation animation

I want to apply an animation to two UIImageViews. The idea is for image one to flip horizontally by 90 degrees and then image two to complete the rotation. Think of it as a coin spinning: Head side (image one) faces forward -> turn 90 degrees -> Tail side (image two) rotates to face forward. I can do the first half of the animation but I am stuck on the second.
[UIView animateWithDuration:1.0f animations:^{
image1.transform = CGAffineTransformMakeScale(-0.01, 1);
} completion: ^(BOOL finished) {
// How can I make image 2 to rotate out as if it initially was already rotated by 90 degrees?
}];
for flipping animation, there a animation option called UIViewAnimationOptionTransitionFlipFromRight, use it with the UIView's animation method for example, like below for example
[UIView transitionWithView:myImageView //with first image
duration:animationDuration
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
myImageView.image = toImage; //to next image
} completion:^(BOOL finished) {
//completion actions after flipped
}];
there are other animation options also there, like FromLeft,
FromTop,FromBottom use any one to your requirement
Take a look at this question about flipping a UIView in 3D using CATransform3D.
Simple Core Animations 3D transform of UIView
The answer:
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -1000.0;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI * 0.6, 1.0f, 0.0f, 0.0f);
[UIView animateWithDuration:1.0 animations:^{
self.someView.layer.anchorPoint = CGPointMake(0.5, 0);
self.someView.layer.transform = rotationAndPerspectiveTransform;
} completion:^(BOOL finished){
// code to be executed when flip is completed
}];

Card flipping animation

I am making a card game and would like to use a Card flipping animation.
Currently I'm using this code with two images, front and back:
card, is a uiview with two UIImageView propertys
[UIView transitionWithView:card duration:0.65f
options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
card.backImageView.image = card.frontImageView.image;
card.layer.shadowOpacity = 0.8;
} completion:^(BOOL finished){
card.layer.shadowOpacity = 0.0;
}];
In order to create a basic card flipping animation like the one in the video you've linked to, I suggest putting frontImageView and the backImageView directly on top of each other on the UIView you intend to flip. To start, set their images to front and back accordingly; and, in this particular case, hide the frontImageView and show the backImageView.
Assuming "card" is the UIView you intend to flip, to perform the flip try:
[UIView transitionWithView:card duration:0.65f
options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
frontImageView.hidden = NO;
backImageView.hidden = YES;
} completion:^(BOOL finished) {
// whatever you'd like to do immediately after the flip completes
}];
Edit:
And to handle the shadow, first off, it appears in the video you posted that the shadow grows in length moreso than it just fades in. And it seems as if (and makes logical sense that) the shadow reaches its peak during the middle of the animation as the card is lifted at its highest point. Since the shadow grows then shrinks during the course of the flip animation, it doesn't make sense to include the shadow animation within the same animation block as the flip since they're on different time schedules.
Secondly with regard to the shadow, to animate the layer property, you have to use Core Animations.
Perhaps you can run the two animations concurrently, i.e. while the above animation is performing, also do something like:
CABasicAnimation *shadowAnimation = [CABasicAnimation animationWithKeyPath:#"shadowRadius"];
shadowAnimation.delegate = self;
[shadowAnimation setFromValue:[NSNumber numberWithFloat:3.0]];
[shadowAnimation setToValue:[NSNumber numberWithFloat:10.0]];
[shadowAnimation setDuration:0.65f];
shadowAnimation.autoreverses = YES;
[[card layer] addAnimation:shadowAnimation forKey:#"shadowRadius"];
The last portion has been adapted from this code and takes advantage of the autoreverse property to automatically reverse the shadow's growth.
This is how to perform a card flipping animation in swift 3:
UIView.transition(from: frontImageView,
to: backImageView,
duration: 0.65,
options: .transitionFlipFromRight,
completion: nil)
i tested a few things, and Compromise with this:
_tempTransform = card.transform;
[card loadFront];//loads the front image.
card.frontImageView.hidden=YES;
[UIView animateWithDuration:0.02f
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -500;
transform = CATransform3DRotate(transform, 15.0f * M_PI / 180.0f, 0, -1, 0.0f);
card.layer.transform = transform;
}completion:^(BOOL done){
card.layer.shadowOpacity=0.1f;
card.transform=CGAffineTransformScale(card.transform, 1.2f, 1.2f);
[UIView transitionWithView:card duration:0.4f
options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
card.frontImageView.hidden=NO;
card.backImageView.hidden=YES;
} completion:^(BOOL finished){
card.layer.shadowOpacity=0.0f;
card.transform=_tempTransform;
}];
}];

CGAffineTransformScale and orientation change

Good evening,
I scale down a UIView by using CGAffineTransformScale.
[UIView animateWithDuration:0.3 animations:^{
gridContainerView.transform = CGAffineTransformScale(CGAffineTransformIdentity, 0.2, 0.2);
gridContainerView.alpha = 0.0;
} completion:^(BOOL finished) {
// show UIView B
}];
and scale it back to its original size:
[UIView animateWithDuration:0.3 animations:^{
gridContainerView.transform = CGAffineTransformIdentity;
gridContainerView.alpha = 1.0;
} completion:^(BOOL finished) {
// remove UIView B
}];
This works fine. The gridContainerView get scaled down to the center of the screen. However, if I change the devices orientation (to a.e. landscape) the center is somehow shifted to the bottom left. The transformation is not going to the center of the screen anymore once I change orientation.
The only way to fix this is to release the gridContainerView and reallocate/init it. But unfortunately this is not an option for me at this point.
Any help is truly appreciated.

iPad - CGAffineTransformMakeRotation - keeping rotation

I have a heads up display (HUD) that I'm trying to get to properly rotate with the view. I created a function orientationWillChange that is supposed to rotate the view and that works fine, just requires a little more programming on the side of the view controller implementing it.
My main problem is that it rotates when it closes. It does some other transformations when it closes (shrinking/fading it so it disappears), but it seems to be rotating it back to "normal".
I don't want to rotate the view another 90 degrees, I just want to make sure it stays in the rotation it is at. How do I do that?
My closing function is as follows:
- (void)close {
_windowIsShowing = NO;
[UIView animateWithDuration:0.125 animations:^{
hudView.transform = CGAffineTransformMakeRotation(rotationDegrees * M_PI / 180);
hudView.transform = CGAffineTransformMakeScale(1.1, 1.1);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.15 animations:^{
hudView.transform = CGAffineTransformMakeScale(0.4, 0.4);
hudView.alpha = 0.0;
backgroundColorView.alpha = 0.0;
} completion:^(BOOL finished) {
[hudWindow resignKeyWindow];
[self release];
}];
}];
}
(fyi this is based on CloudApp's HUD)

Resources