I'd like to extend a class from UIImageView,which will infinite rotate a universe image. So I can simply put this image view as background view for other UI elements.
3 questions here:
Is it the right way to extend from UIImageview class.
How to keep rotating infinite, and as background, when put it into other views, I don't need to write extra lines of code.
I wrote a rough prototype, when I put it into other views as background, all UI elements in this view are rotating with the image.
Assume that you have a UIImageView and assign an image on it and named myImgView. On viewDidLoad, add your code as bellow:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
[UIView setAnimationRepeatCount:MAXFLOAT];
myImgView.transform = CGAffineTransformMakeRotation(M_PI);
[UIView commitAnimations];
It works for me like a charm.
There is nothing wrong in extending UIImageview Class.
Create rotation animation and set repeat ON.
Do not add element on rotating image. (Add elements in base view. Insert rotating imageview at index 0).
From the UIView Class Reference:
The UIImageView class is optimized to draw its images to the display. UIImageView will not call drawRect: a subclass. If your subclass needs custom drawing code, it is recommended you use UIView as the base class.
At present, UIImageView subclasses do work, especially if they don't interfere with the drawing code. Just don't complain to apple if a future iOS update breaks your subclass. It's easy enough to write your own UIView subclass to display an image. If you already have an appropriate graphics, consider just placing it in CALayer contents, instead of implementing the UIView drawRect method.
Rotations by changing UIView transform (which is of type CGAffineTransform) always take the shortest path. This means that a clockwise rotation of 270 degrees is animated as an anticlockwise rotation of 90 degrees, and any multiple of 360 degrees will do nothing. You can get 360 degree rotations if you obtain the view's layer, and animate CALayer transform (which is of type CATransform3D). See Can I use CGAffineTransformMakeRotation to rotate a view more than 360 degrees?
To make the animation repeat endlessly, the CAMediaTiming Protocol Reference recommends setting repeatCount to HUGE_VALF.
Related
I am talking about that effect when user presses button to take photo, it shrinks and moves to toolbar? How is this achieved in general?
You can create this by both scaling (applying a transform) and moving (animating the position) of the image.
I wrote about a similar animation (the Open in Background animation from Safari on iPhone) in this blog post. Not all of the code is necessary but some part of it will be useful for the animation you are trying to do.
You should
Calculate the scale factor to make the image the appropriate size
Calculate the path you want to animate the image along.
Animate a scale with the calculated scale factor
Animate a position animation along the path (using a CAKeyframeAnimation)
Since you are doing two animations at once you could benefit from using a CAAnimationGroup.
Since you are animating down to a toolbar which probably is another part of the view hierarchy than where the image is you may need to use method like
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view
and
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view
To translate coordinates between the different views.
so the shrink animation is achived by
[UIView beginAnimations:#"animationShrink" context:NULL];
[UIView setAnimationDuration:kSlideInAnimationDuration];
flipFlopContainer.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(shrinkAnimationFinished:)];
[UIView commitAnimations];
after this animation in shrinkAnimationFinished method you need to define a path to follow and change the position of your view accroding to that path.
See the following thread for that animation
Resize and move a UIView with Core Animation (CAKeyFrameAnimation)
I have a UILabel I want to animate growing and shrinking. While the size changes I need the bottom left corner to remain static so that it always appears directly above a bottom toolbar. I am using the following code to make the label grow:
[UIView animateWithDuration:kAnimationDuration delay:0.0 options:UIViewAnimationCurveEaseInOut
animations:^{
CGFloat lblHeight = 42.0f;
[label setFrame:CGRectMake(0.0,
CGRectGetMaxY(self.view.bounds) - kBottomBarHeight - lblHeight,
CGRectGetMaxX(self.view.bounds),
lblHeight)];
} completion:^(BOOL finished) { }];
and to make it shrink I use the same logic except that lblHeight is set to 17.0f
The view correctly grows but when I try to shrink it the frame change animation is not animated. It blips into the new size and then animates into the new origin/location. I need the frame change to be animated. Can anyone see what I'm doing wrong?
After some tinkering I've managed to get the desired behavior by doing the following.
In the expand method, I use the UIView animation to alter the frame.
In the shrink method, I use the UIView animation to alter the bounds and center.
I'm a little baffled as to why this works but trying to shrink with the frame does not. If anyone can share some insight into this that would be great.
You should not really use frames to animate, rather you should use the transform property of your label.
However, since you want one corner to remain static, I think its best you use Core Animation. CALayer has a property called anchorPoint that determines which point a layer will rotate with respect to, and I'm pretty sure it is also valid for grow/shrink effects.
Is there a way to make drawRect animate FROM THE PREVIOUS SCENE to the next one?
(Amazingly) you can animate inside drawRect - try it. You can fade, translate or animate any other property.
However, it starts "from fresh", from blank. So for example if you put a fade-in animation block in drawRect, the previous scene with disappear and the new scene will fade up from white.
I want the screen to fade from the previous image (drawn in the previous cycle of drawRect) to the new image I have just drawn ... err, am drawing.
Is there a way to do that, perhaps trickily by manipulating what's going on with drawRect?
This would seem to be a very common use case - blending from one scene to the next.
Does anyone know the secret?
Of course, obviously this can be done in the core animation milieu or in many other ways, but having drawRect fade from one drawRect to the next is an obvious idea. Cheers.
Astounding update thanks to the genius of WrightCS.....
Thanks only to WrightCS, we now know that drawRect handles animations perfectly. Simply paste this code at the end of any drawRect and try it:
self.alpha = 0.0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2];
self.alpha = 1.0;
[UIView commitAnimations];
it treats the entire drawRect, no matter how complex, as one enormous block and it wraps it in that animation. Yes, it even includes painted in offscreen areas, bitmap rendering or anything else. Everything gets animated. Who knew?
The problem at hand - how to make it start the animation from the previous scene rather than start from blank?
Drawrect Is invisible. It happens in the 'backbuffer' which the iOS displays on screen only when you're ready with drawRect. So you can definitely not animate while in drawrect. However, you can commit animation instrucions from just about anywhere, including drawrect. But the animation will be performed afterwards.
Animation requires timing and showing different frames to the user.
You CAN do that all by yourself (constantly forcing a redraw and doing something slightly different in drawrect each the time) but that's a lot of work, especialy if you want it done right.
Luckily iOS has many animation effects programmed for you. Either using Core Animation, or the (more simple and basic) animation in UIKit. But since it works by animating certain properties of views (eg the alpha of a whole view, or the rotation of a whole view, ...) you might need to rearrange your views and subviews to make good use of it.
E.g. Each horse limb is separate subview and you animate their transformations (no redraw needed, iOS will do the rest)
E.g. The old and new frame are two separate views and you animate the new frame (which is on top) from alpha 0 to alpha 1.
You can animate the alpha:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
myObject.alpha = 0.0;
[UIView commitAnimations];
if you are under iOS 5.0+, you can use the following:
...
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionBeginFromCurrentState
animations:^{
//do your stuff here
}completion:^(BOOL finished) {
//completition stuff go here
}];
...
The best thing you can do is to use two UIView instances and animate between them.
When you are starting the animation you have to know which is the original and final state of the animation. That's difficult if it's only one view.
I am rotating a UIImageView in place periodically. My view is very basic, a view inside of a UITabBar view set. If I happen to rotate my iPad while my rotation is animating then my image becomes skewed. I have checked everything I can think of in my xib file for my image, the autoresizing is turned completely off and I am not auto-resizing subviews on the parent view.
Here is my animation code:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationDelay:0.0];
transform = CGAffineTransformMakeRotation(convertToRadian(myDegrees));
myImage.transform = transform;
[UIView commitAnimations];
If I take my animation out then everything works as I would expect. This rotation code appears to work fine if I do not rotate my device.
What can I do to keep the built-in rotation animation from altering my animation and skewing my images?
After many different attempts, what I ended up doing here is adding a clear view with my rotating images inside of it and setting the "auto-resize sub views" to off in interface builder. You can also do this in code as needed. I had to add the UIView placeholder because the super view containing my rotating images needed to auto-resize other view objects on rotation, but this fixed the funky skewing of my images due to animation of orientation change at the same time as animating a manual rotation in place.
Hope this helps someone.
The coordinate system gets changed. I've figured this much out too... thought I had a bug. If you save the CG ... GState, then you can revert back to the coordinate system initially used. This is in Deitel and Deitel's book. I just found it. Wanted to post it for anyone also looking.
You got a clever trick though! I might use it if this won't work.
I want to rotate a UILabel in semicircle.
So what I am planning to do is use some timing function like CaMediaTimingFunction.
I want to use getControlPointAtIndex method of CaMediaTiming Function so that I can get a set of points to rotate the UILabel. The points which I will get will help me in forming the frame for UILabel.
Does anybody have good idea other than this.
I want to rotate the Label in a semicircle very smoothly.
If all you want to do is rotate the label in an animated fashion, you should just be able to set the transform property of the UILabel within an animation block, like the following:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:5.0f];
label.transform = CGAffineTransformMakeRotation(90.0f * M_PI / 180.0f);
[UIView commitAnimations];
This will rotate your label by 90 degrees over a duration of 5 seconds.
If you wish to control the clockwise / counterclockwise direction of the rotation, you can refer to this answer, which shows how to use lower-level Core Animation keyframe animations to do this.
If you're making a game, you might want to take a look at cocos2d - it has some simple rotation & timer actions that are pretty easy to use.
http://code.google.com/p/cocos2d-iphone/