Why Won't My Image Rotate in Xcode? - iphone

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 ;-)

Related

How to create a rotating circle?

I'm trying to make a simple "rotating gear animation." Basically, I want to put a circle on the screen at a certain position, and give this circle an image of gear (or just make the image rotating without creating a circle at first). Also, the gear should keep rotating. How can I achieve that?
I'm beginner to ios development. If anyone can provide a simple sample code, I will really appreciate that!
You have to actually rotate a UIImageView infinitely.
Firstly #import <QuartzCore/QuartzCore.h>
- (void) runSpinAnimationOnView:(UIView*)view duration:(CGFloat)duration rotations: (CGFloat)rotations repeat:(float)repeat;
{
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat;
[view.layer addAnimation:rotationAnimation forKey:#"rotationAnimation"];
}
Assume that you have a UIImageView and assign an image on it and named ImgView. On viewDidLoad, add your code as below:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationRepeatCount:MAXFLOAT];
ImgView.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
From the links :-
UIView Infinite 360 degree rotation animation?
Infinite rotating image background UIImageView

CATransform3DMakeRotation causes UIimage rotation along with UIimageview

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.

How can I present a UIView from the bottom of the screen like a UIActionSheet?

I'd like a UIView to slide up from the bottom of the screen (and stay mid-screen) like a UIActionSheet. How can I accomplish this?
UPDATE:
I am using the following code:
TestView* test = [[TestView alloc] initWithNibName:#"TestView" bundle:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
test.view.center = CGPointMake(160,100);
//test.view.frame = CGRectMake(0, 0, 160, 210);
[[[UIApplication sharedApplication] keyWindow] addSubview:test.view];
[UIView commitAnimations];
The view seems to be animating from the corner and appearing in the corner. How can I make it slide up from the bottom? Getting close!
Do what Matt did here, but just change the values and direction. I have code at home to do this from the bottom if you need it later (I'll update this post).
Link: http://cocoawithlove.com/2009/05/intercepting-status-bar-touches-on.html
Also, don't forget to take out the bit of code that shifts the main view downward (so instead the UIView just pops over top like an ActionSheet)
Updated with code:
This is what I use in one of my apps to show/hide a little "options" view:
- (void)toggleOptions:(BOOL)ViewHidden
{
// this method opens/closes the player options view (which sets repeat interval, repeat & delay on/off)
if (ViewHidden == NO)
{
// delay and move view out of superview
CGRect optionsFrame = optionsController.view.frame;
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
[optionsController.view
performSelector:#selector(removeFromSuperview)
withObject:nil
afterDelay:0.5];
[optionsController
performSelector:#selector(release)
withObject:nil
afterDelay:0.5];
optionsController = nil;
}
else
{
optionsController = [[PlayOptionsViewController alloc] init];
//
// Position the options at bottom of screen
//
CGRect optionsFrame = optionsController.view.frame;
optionsFrame.origin.x = 0;
optionsFrame.size.width = 320;
optionsFrame.origin.y = 423;
//
// For the animation, move the view up by its own height.
//
optionsFrame.origin.y += optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[window addSubview:optionsController.view];
[UIView beginAnimations:nil context:nil];
optionsFrame.origin.y -= optionsFrame.size.height;
optionsController.view.frame = optionsFrame;
[UIView commitAnimations];
}
}
One way would be to use the present modal view controller on the view controller:
presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated
For more info take a look at the UIViewController documentation.
EDIT: If you want a mid-screen view you'll need to animate it into position as #jtbandes has pointed out. I suggest also adding some candy to UIView animation block:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.4];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
myView.center = CGPointMake(x,y);
[UIView commitAnimations];
You can then move it again if you need to go full screen or dismiss it.
You'll have to move the view yourself, by setting its center or frame. I'll let you figure out what to set those to. But for the animation:
// set the view to its initial position here...
[UIView beginAnimations:nil context:NULL];
// move the view into place here...
[UIView commitAnimations];
Check out this post: http://blog.yetanotherjosh.com/post/33685102199/3-ways-to-do-a-vertical-transition-with
I'm going with the modal window approach.
Try this solution.... it works
#pragma mark - Date Selector View PresentModelView with Transparent ViewController
- (void) showModal:(UIView*) modalView {
CGRect rect=modalView.frame;
rect.origin=CGPointMake(0, 0);
self.tutorialView.frame=rect;
UIWindow *mainWindow = [(AppDelegate *)[UIApplication sharedApplication].delegate window];
CGPoint middleCenter;
middleCenter = CGPointMake(modalView.center.x, modalView.center.y);
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
modalView.center = offScreenCenter;
if ([[mainWindow subviews] containsObject:modalView]) {
[modalView removeFromSuperview];
}
[mainWindow addSubview:modalView];
[mainWindow bringSubviewToFront:modalView];
// Show it with a transition effect
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
// animation duration in seconds
modalView.center = middleCenter;
[UIView commitAnimations];
}
// Use this to slide the semi-modal view back down.
- (void) hideModal:(UIView*) modalView {
CGSize offSize = [UIScreen mainScreen].bounds.size;
CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
[UIView beginAnimations:nil context:(__bridge void *)(modalView)];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(hideModalEnded:finished:context:)];
modalView.center = offScreenCenter;
[UIView commitAnimations];
}
- (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIView *modalView = (__bridge UIView *)context;
[modalView removeFromSuperview];
}

Fade to black within a uinavigationcontroller?

I want to fade the whole screen (including navigation bar) to black when a user presses a button on a uinavigationcontroler, before showing a new view. (i don't want to push this new view, for various reasons).
How would I achieve this?
EDIT
Thanks to Mac and Eiko, I have figured it out. Here's the code I used. Not sure if it is optimal, but it does the trick.
// this is called from a programmatically constructed button.
// change (void) to (IBAction) if linking from IB.
- (void)fadeAndShow:(id)sender
{
// blackView is a #property which has been #synthesize-d
// do I really need to alloc and init this?
blackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
blackView.alpha = 0.0;
[blackView setBackgroundColor:[UIColor blackColor]];
[self.navigationController.navigationBar.superview addSubview:blackView];
[UIView beginAnimations:#"fadeAway" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDidStopSelector:#selector(showNewScreen:finished:context:)];
blackView.alpha = 1.0;
[UIView commitAnimations];
}
-(void)showNewScreen:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
// I guess you could fade in somewhere in the new view controller.
// don't know how to fade back in this view tho... viewDidAppear?
NewViewController *controller = [[NewViewController alloc] initWithNibName:#"NewView" bundle:nil];
[self.navigationController setNavigationBarHidden:YES];
controller.hidesBottomBarWhenPushed = YES;
[[self navigationController] pushViewController:controller animated:NO];
[blackView removeFromSuperview];
[controller release];
}
Off the top of my head (I haven't actually tested the following at all):
-(IBAction) buttonClicked:(id) sender
{
[UIView beginAnimations:#"myAnimation" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
blackView.alpha = 1.0;
[UIView commitAnimations];
}
Create a UIView in the navigationbar's superview (which I'm assuming is window-sized) that is the same size as the window.
Set that view's backgroundColor to [UIColor blackColor], and its alpha to 0.0.
In your button handler do something like the above (assuming your new UIView is blackView and ANIMATION_DURATION is your desired animation time in seconds).
Then, add your new view on top.
EDIT: too quick for me Eiko! Also, code at the top since the ordered list seems to screw around with the code formatting - sorry the answer reads a little odd.
You can add a black coloured UIView in screen size on top of your current view, and animate its alpha from 0 to 1. When the animation is done, add your new view. You can remove the black one then. Animate from 1 to 0 for the opposite effect - going from black to the content).

Why no animation in PageControl project?

I'm using the PageControl project, which is on Apple's dev site. I've added a flip view to the project and an info icon to the top right of each view/page. For some reason, only the first page is able to animate the flipping. Page 2 on still shows the flipped page but does not animate. To make sure it isn't anything special about page 1, I switch page 1 and 2 and that worked fine. Page 2 in position 1 animated while Page 1 in position 2 did not. Any ideas why this would happen or how I can trouble shoot it?
I did take a look at this thread, which seems to be the same issue: Flip View Iphone. However, My flipview is a UIViewController and so is the class with the info icon on it. In the other thread, they are using UIViews.
I did implement the showInfo code from the above thread. When on Page 2, I see no flip. Then I scroll over to Page 1 and see it has flipped. Not sure why it isn't staying with Page 2. When on Page 1, it doesn't animate the flip. The flipview just suddenly appears.
Do you have a containerView? Something that can be there so you can add and remove subviews from it? Animation can break if you have two viewControllers, one coming and one going, without a containerView. I use a rootViewController and animate all my pages to and from each other with the rootViewcontroller in the back. Here is my code for flipping, you'll probably have to do a little editing to make it work for you:
(keep in mind that self is the rootViewcontroller, a viewcontroller with a blank view (color it so it matches your views))
- (void)switchTwoViews:(UIViewController *)view1 otherView:(UIViewController *)view2
{
/*
This method is called to switch views.
It flips the displayed view from the main view to the flipside view and vice-versa.
*/
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
[view1.view setUserInteractionEnabled: NO];
[view2.view setUserInteractionEnabled: NO];
if (view1.view.superview == nil) {
coming = view1;
going = view2;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else {
coming = view2;
going = view1;
transition = UIViewAnimationTransitionFlipFromRight;
}
// in some cases the following is needed to size the view
// coming.view.frame = [UIScreen mainScreen].applicationFrame;
// going.view.alpha = 1.0; //uncomment these lines if we want fading of views
// coming.view.alpha = 0.0;
NSArray *viewArray = [[NSArray alloc] initWithObjects:coming, going, nil];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[UIView beginAnimations:#"View Flip" context:viewArray]; {
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidEnd:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// coming.view.alpha = 1.0; //uncomment these lines if we want fading of views
// going.view.alpha = 0.0;
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[self.view addSubview: coming.view];
}
[UIView commitAnimations];
}
- (void) animationDidEnd:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
NSArray *viewArray = context;
[((UIViewController *)[viewArray objectAtIndex:1]).view removeFromSuperview];
[[viewArray objectAtIndex:1] viewDidDisappear:YES];
[[viewArray objectAtIndex:0] viewDidAppear:YES];
[[[viewArray objectAtIndex:0] view] setUserInteractionEnabled: YES];
[viewArray release];
}