CATransform3DMakeRotation causes UIimage rotation along with UIimageview - iphone

I am facing a problem with UIImageView rotation.
I need to rotate the UIImageView horizontally with animation like ads.
To do this I am using the following code:
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
if (baddview) {
baddview = FALSE;
adimageView.layer.transform = CATransform3DMakeRotation(0, 0, 1, 0);
} else {
baddview = TRUE;
adimageView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0);
}
}
completion:^(BOOL finished) {
}
];
The imageview is rotating as I need it but the image in the image view is appearing reversed, like after a 180 degrees rotation (you can see the image here).
How can I animate the UIImageView rotation without rotating the UIImage?

One possible approach is making 2 UIImageViews, and animating them. What you would have to do is:
Before the animation block, create the new UIImageView and place it behind the current UIImageView, but make sure that it has a rotation of 180.
Make two animation blocks, one that rotates the first view 90 degrees at half (ie 0.5 sec) the duration, and the other block animates the view behind to CATransform3DIdentity at full duration (ie 1.0 sec).
I will add some code if needed.
Or alternatively, set the isDoubleSided property of CALayer to NO. Then, rotate both views 180 degrees. The top view will be hidden, since it is not double sided.
I just created a new single-view project, and added a UIButton to perform the flip. Here is the rest of the code:
Header File:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIImageView* _imageView1;
UIImageView* _imageView2;
}
- (IBAction)flip:(id)sender;
#end
Implementation file:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIImage* image1 = [UIImage imageNamed:#"gaara1.png"];
_imageView1 = [[UIImageView alloc] initWithImage:image1];
[_imageView1 setFrame:CGRectMake((CGRectGetWidth(self.view.bounds) - 300)/2, 100.f, 300, 75)];
UIImage* image2 = [UIImage imageNamed:#"gaara2.png"];
_imageView2 = [[UIImageView alloc] initWithImage:image2];
[_imageView2 setFrame:CGRectMake((CGRectGetWidth(self.view.bounds) - 300)/2, 100.f, 300, 75)];
// the second imageView is in the back
[self.view addSubview:_imageView2];
[self.view addSubview:_imageView1];
}
- (IBAction)flip:(id)sender {
[_imageView1.layer setDoubleSided:NO];
[_imageView2.layer setDoubleSided:NO];
[_imageView1.layer setZPosition:10.f];
[_imageView1.layer setTransform:CATransform3DIdentity];
[_imageView2.layer setTransform:CATransform3DMakeRotation(-M_PI, 1.f, 0.f, 0.f)];
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
_imageView1.layer.transform = CATransform3DMakeRotation(M_PI, 1.f, 0.f, 0.f);
_imageView2.layer.transform = CATransform3DIdentity;
}
completion:NULL];
}
#end
The images:

Your code is likely to cause problems. UIView animations are for animating the properties of a UIView, not layers.
I expect problems if you try to manipulate layer transforms in a UIView animation block. You should limit yourself to changing view properties in a UIView animation block:
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
_imageView1.transform = CGAffineTransformMakeRotation(M_PI);
_imageView2.transform = CGAffineTransformIdentity;
}
completion:NULL];
CAAnimation objects are for animating layers.
If you want to animate your view's layer transform, either do it directly (which will give you an implicit animation) or create a CABasicAnimation object to do more complex animations.

Related

Check Intersect for programmatically generated image views

i Have two images generated like this
- (void)moveImage:(UIImageView *)image duration:(NSTimeInterval)duration
curve:(int)curve x:(CGFloat)x y:(CGFloat)y
{
// Setup the animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
[UIView setAnimationBeginsFromCurrentState:YES];
// The transform matrix
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
image.transform = transform;
// Commit the changes
[UIView commitAnimations];
}
- (void)alien {
enemy =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"alien.png"]];
enemy.frame = CGRectMake(-100, 20, 50, 50);
[self.view addSubview:enemy];
// Move the image
[self moveImage:enemy duration:5
curve:UIViewAnimationCurveLinear x:460 y:0.0]; }
- (void)bullet4 {
bullet =
[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Bullet.png"]];
bullet.frame = CGRectMake(carDude.center.x, 380, 5, 10);
[self.view addSubview:bullet];
// Move the image
[self moveImage:bullet duration:3
curve:UIViewAnimationCurveLinear x:0 y:-500.0]; }
I'm trying to hide them when they intersect. There can be many on the screen at the same time but i tried,
-(void)checkCollision {
if(CGRectIntersectsRect(bullet.frame, enemy.frame)) {
}
}
and no luck getting the images to do anything when they collide.
How can i get the image to hide and check collision?
If you change the transform of a view, its frame doesn't change (it can even become unvalid) and should be ignored.
From the documentation:
Warning If this property is not the identity transform, the value of the frame property is undefined and therefore should be ignored.
Since all you're doing is applying a translation transform, why don't you animate the frame instead?

iPhone trying to use a block animation to simulate a card flip, but nothing happens no animation

I'm trying to do a card flip animation...but nothing happens.
this is what I do
1. create a container view, to hold the two views to animate from.
2. Create the first view.
3. add it to the container.
4. create the second view
3. start the animation block, beginAnimations
4. call setAnimationTransition put in the view container
5. add the second view to the view container
6. commit the animation,
my code
// create container view
CGRect viewRect = CGRectMake(10, 10, 100, 100);
UIView* myView = [[UIView alloc] initWithFrame:viewRect];
// create 2 viues to flip between for animation
UIImage *i= [ UIImage imageNamed : #"card1.jpg"];
UIImageView *topCard=[ [UIImageView alloc] initWithImage: i ];
topCard.frame= CGRectMake(0,0,100,100);
[myView addSubview:topCard];
[self.view addSubview:myView];
i= [ UIImage imageNamed : #"card2.jpg"];
UIImageView *butCard=[ [UIImageView alloc] initWithImage: i ];
butCard.frame= CGRectMake(0,0,100,100);
// set up the animation
[UIView beginAnimations:#"Flip Top Card" context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationRepeatCount:0];
[UIView setAnimationRepeatAutoreverses:NO];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut ];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:myView cache:YES];
[myView addSubview:butCard];
// start the animation
[UIView commitAnimations];
-Ted
If this is iOS 4.0 or later you can do:
[UIView transitionWithView:myView
duration:0.3f
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^(void) {
self.topCardIsShown = !self.topCardIsShown;
self.topCard.hidden = !self.topCardIsShown;
self.butCard.hidden = self.topCardIsShown;
}
completion:^(BOOL finished) {
// nothing
}];
This assumes that you have added both card views to the myView and have added a #property(nonatomic, assign) BOOL topCardIsShown; to your class.

How can I rotate a UIButton continuously and be able to stop it?

I want to rotate a UIButton continuously as a means of indicating that an app is recording something. Is this a good idea. I also want to be able to stop this continuous rotation.
How would I use animation to do this?
Use the UIView animation method:
animateWithDuration:delay:options:animations:completion:
and use the option UIViewAnimationOptionRepeat
For example for a UIButton * outlet named button:
- (void)viewDidLoad
{
[super viewDidLoad];
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionRepeat | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
self.button.transform = transform;
} completion:NULL];
}
Since it's going round and round, I just rotate it by pi radians rather than 2pi. you could use any angle you want.
Edit
To stop the animation, just create another animation of a short duration beginning from the current state, e.g.
- (void)stopRotating {
[UIView animateWithDuration:0.1 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveLinear animations:^{
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI * 0.05);
self.button.transform = transform;
} completion:NULL];
}
This provides a very short animation which overrides the current animation. Note that the angle of the transform is multiplied by 0.05 which is the ratio of 0.1/2.0 which means that the rotational speed for this little segment is the same as the continuous rotational speed.
Try below code that will help you because I run that code successfully.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
CABasicAnimation *halfTurn;
halfTurn = [CABasicAnimation animationWithKeyPath:#"transform.rotation"];
halfTurn.fromValue = [NSNumber numberWithFloat:0];
halfTurn.toValue = [NSNumber numberWithFloat:((360*M_PI)/180)];
halfTurn.duration = 0.5;
halfTurn.repeatCount = HUGE_VALF;
[[button layer] addAnimation:halfTurn forKey:#"180"];
I had the same problem myself. In the end I made it like that:
#pragma mark Start/StopSpining
-(void)startSpin{
isSpining = YES;
[self Spin];
}
-(void)stopSpin{
isSpining = NO;
}
-(void)spin{
[UIView animateWithDuration:1.0 delay:0 options: UIViewAnimationOptionCurveLinear animations:^{
self.spinCircle.transform = CGAffineTransformRotate(self.spinCircle.transform, M_PI/2);
} completion:^(BOOL finished) {
if (isSpining)
[self spin];
}];
}
Try below extension for swift 3.
extension UIView {
func rotate360Degrees(duration: CFTimeInterval = 3) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = CGFloat(M_PI * 2)
rotateAnimation.isRemovedOnCompletion = false
rotateAnimation.duration = duration
rotateAnimation.repeatCount=Float.infinity
self.layer.add(rotateAnimation, forKey: nil)
}
}
For start rotation.
MyButton.rotate360Degrees()
And for Stop.
MyButton.layer.removeAllAnimations()
I suggest you don't rotate the UIButton, just the image you put on the button. Who knows what complications or overhead rotating a rectangular object that can detect touches introduces - what happened if your user somehow taps in the corner of the button and then releases the tap as the button has rotated so that the touch is now outside? Does that register a touch up inside or not?
Anyway, if you want continuous rotation use a block method:
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion
seems to fit the bill. The complete rotation (2pi) will occur every duration and you cause it to repeat until you stop it using UIViewAnimationOptionRepeat. You can check with completion to see if you should begin another cycle when one animation cycle has ended and you can stop the animation at any time with
[myView.layer removeAllAnimations];
(If you simply want to run it until you stop it then there are other variants of this method without a completion block)
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
uiButtonObject.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
M_PI is the radian value of the angle you want to rotate. Run this in a loop and in a different thread. You might also want to run the above using performSelectorInMainThread method as UI changes are not permitted in the UIThread.

Why Won't My Image Rotate in Xcode?

I'm trying to do a simple animation that will rotate an image continuously when a button is clicked, but for some reason when I click the button it crashes the app.
Here's my code.
.h file:
#interface MainView : UIView {
}
IBOutlet UIImageView *sunray;
- (IBAction)pushrotate:(id)sender;
#end
.m file:
#implementation MainView
- (IBAction)pushrotate:(id)sender {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0];
sunray.transform = CGAffineTransformMakeRotation(6.2831855);
[UIView commitAnimations];
}
-(void) dealloc {
[sunray dealloc];
[sunray release];
[super dealloc];
}
#end
Any idea how I can make it work? Also, what is the best way to make the animation start as soon as the app loads?
If you set your view rotation angle a multiply of 2*PI (it looks so in your case), then the view recognises that transformation does not actually have an effect and view is not rotated.
To rotate your view by angle more then 2*PI with animation you need to use CoreAnimation. So your code should look smth like:
//link with QuartzCore.framework
#import <QuartzCore/QuartzCore.h>
...
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 1.0f;
[sanray.layer addAnimation:animation forKey:#"MyAnimation"];
You probably wired the action or the outlet up wrong (if you posted more console output, we would be sure). See if Interface Builder has any error markers on your actions/outlets.
Also see my comment about calling dealloc yourself - you shouldn't, except for [super dealloc] in your own dealloc implementation.
here is my solution to rotate a image
-(void)rotate:(int)degree {
float rad = M_PI * (float)degree / 180.0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
aktivImageView.transform = CGAffineTransformMakeRotation(rad);
[UIView commitAnimations];
}
i think you can also use this code snip with a button
in your IBAction you can code [self rotate:90]; to rate in 90°
or you can use [self rotate:0]; to not rotate your image ;-)

Animate move and scale of image UIButton

I want it to be animated so I'm using [UIView beginAnimations]
I've tried animating using button.imageView.frame (with image set as imageView) but it only animates the position, the image doesn't get scaled down at all.
using hateButton.frame (when image is set as backgroundImage), the backgroundImage gets scaled down but it's not animated.
How do I animate-scale a UIButton image?
You can call layoutIfNeeded between [UIView beginAnimations] and [UIView commintAnimations] or with [UIView animateWithDuration].
[UIView animateWithDuration:0.3f animations:^{
self.myButton.frame = aFrame;
[self.myButton layoutIfNeeded];
}];
I could achieve this using Quartz 2D:
// move anchor point without moving frame
CGRect oldFrame = hateButton.frame;
hateButton.layer.anchorPoint = CGPointMake(0, 1); // bottom left
hateButton.frame = oldFrame;
[UIView beginAnimations:nil context:NULL];
CGAffineTransform newTransform;
newTransform = CGAffineTransformMakeScale(0.8, 0.8);
hateButton.transform = CGAffineTransformTranslate(newTransform, 0, -160);
[UIView commitAnimations];
Make sure you import Quartz2D too:
#import <QuartzCore/QuartzCore.h>