Animation Like frames/Blocks - iphone

Does anyone know how to animation an image in Objective-C like it is done at
Famous Brands (Requires Flash Player to see)

Take your image and slice it in parts with your favorite photo app. Create an imageView for each image and add it to a new UIView which play the role of the image container. Now add this UIView to your main view.
If you want to animate it simply iterate through all imageViews inside your container view and start the following animation:
[UIView animateWithDuration:0.3
delay: i * 0.3
options:UIViewAnimationCurveEaseInOut
animations:^{
currentImageView.alpha = 0.0;
currentImageView.transform = CGAffineTransformMakeScale(0.0, 1.0);
}
completion:nil
];
Where currentImageView is the current imageView in the loop and i the iterator var.
It would be even better to slice the original Image with CoreGraphics, so you don't have to do it manually as stated above but that's a little bit more work.

Related

CGAffineTransform and scaling to center of the image

I started studying objective-c using the iPhone and iPad apps for Absolute Beginners by Rory Lewis book but i got stuck on the 5th chapter.
I want to make a button that shrinks an image.
My problem is, that after I wrote all the code, the image shrinks to the point (0, 0) of the UIImageView (the top left), while in the video the image shrinks to its center. I've done some research and found out that CGAffineTransform uses the center of the object to make translations, rotations etc.
So why does it not work in my case?
I have the latest Xcode version and haven't done anything strange.
I hope I've been clear. Sorry for my English.
EDIT
Sorry for the code, but i wrote the question from my phone.
Anyway the incriminated part goes something like this
- (IBAction)shrink:(id)sender {
if(hasShrink == NO){
[shrinkButton setTitle:#"Grow" forState:UIControlStateNormal];
}
else if(hasShrink == YES){
[shrinkButton setTitle:#"Shrink" forState:UIControlStateNormal];
}
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
myIcon.transform = CGAffineTransformMakeScale(.25, .25);
hasShrink = YES;
[UIView commitAnimations];
}
All the animations are correctly written and the app does work, it just shrinks to the top left. Why is the point not set to the center of the UIImageView by default like it should be?
EDIT:
I figured out it was a problem caused by AutoLayout.
Once disabled everything went smooth ;)
If you are transforming a view mangled managed by auto-layout, you may experience some strange side-effects. See this answer for more details.
The solution I ended up employing was to encapsulate the view I wanted to transform inside another view of exactly the same size. The outer view had the appropriate layout constraints applied to it while the inner view was simply centered in its container. Applying a CGAffineTransform scale transform to the inner view now centers properly.
Old question... but just in case others come looking:
The CGAffineTransform acts (rotates, scales) around an anchorPoint.
If you are sizing to 0, 0 then your anchor point is set to 0, 0. If you want it to size to a different point, such as the center of the image, you need to change the anchor point.
The anchor is part of a layer
So if you have a UIImageView called imageview, you would make a call like this to set the anchor to the center of imageview:
[imageview.layer setAnchorPoint:CGPointMake(0.5, 0.5)];
Try something like this:
CGAffineTransform t = CGAffineTransformMakeScale(0.5, 0.5);
CGPoint center = imageView.center; // or any point you want
[UIView animateWithDuration:0.5
animations:^{
imageView.transform = t;
imageView.center = center;
}
completion:^(BOOL finished) {
/* do something next */
}];
Next time show your code. It will be easier to help you.
Check this project: https://github.com/djromero/StackOverflow/archive/Q-13706255.zip
You must study how autolayout and autoresize affect your views. In the project above both are disabled to let you see how it works.

How to implement the system camera app's shrink animation effect?

The system's camera app has a UI effect. After taking a photo, it will show the animation, which is the photo shrink and move to the left bottom corner.
How can I implement the effect in my app?
Thanks.
In the view that you're trying to shrink call something like this code:
[UIView animateWithDuration:1.0 animations:^{
// self is the view in this case
// if you call this from the controller, use self.view
self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, smallWidth, smallHeight);
self.bounds = CGRectOffset(self.bounds, amountToMoveX, amountToMoveY);
}];
This might not be exactly the animation you're looking for but it should give you a good start.

transition from A image to B image with animation

I have an UIImageView of an white color arrow image. I am animating it to rotate 90 degree's. I also want that UIImageView to change to a black color arrow image as it rotates.
The only solution I can think of is to stack the two images on top of each other, animate both when ever it rotates and change the white color arrow image's alpha (so it fades in and out).
Is there a simpler way to obtain this effect?
Is there a build in transition effect to fade one image out and another image in?
You seem to have a good grasp of what to do. Probably the easiest repeatable way to do this is to create a UIView subclass and add both of your arrows to it. Then add a couple of functions like these.
-(void)rotate90{
blackArrow.alpha = 0;
[self bringSubviewToFront:blackArrow];
[UIView animateWithDuration:1 animations:^{
blackArrow.alpha = 1;
blackArrow.transform = CGAffineTransformMakeRotation(M_PI_2);
whiteArrow.transform = CGAffineTransformMakeRotation(M_PI_2);
}];
}
-(void)rotate0{
whiteArrow.alpha = 0;
[self bringSubviewToFront:whiteArrow];
[UIView animateWithDuration:1 animations:^{
whiteArrow.alpha = 1;
blackArrow.transform = CGAffineTransformMakeRotation(0);
whiteArrow.transform = CGAffineTransformMakeRotation(0);
}];
}

iPad - No user interaction on view animated on-screen

Alright this is a newbie question, so I apologize in advance. I have a UIView which I laid out in Interface Builder off-screen. When the user presses a button, I would like to animate this view on-screen. It works, but I can't interact with any buttons in the UIView. I have read that only the view is moved when you animate and that the actual objects retain their positions, so I have tried setting the position of the UIViews' layers, but it causes my UIView menu to display an extra 81 pixels to the left. When this happens, I can interact with the buttons, but I need it to be flush with the right of the screen. Here is my code in the IBAction on the openMenu button:
CABasicAnimation *moveView = [CABasicAnimation animationWithKeyPath:#"position"];
moveView.delegate = self;
moveView.duration=0.5;
// If the menu is displayed, close it!
CGPoint currentPosView = [[entirePage layer] position];
CGPoint destView;
[moveView setFromValue:[NSValue valueWithCGPoint:currentPosView]];
if (menuDisplayed) {
// Move right to our destination
destView.x = currentPosView.x;
destView.y = currentPosView.y + 81;
[moveView setToValue:[NSValue valueWithCGPoint:destView]];
// Otherwise, open it
} else {
// Move left to our destination
destView.x = currentPosView.x;
destView.y = currentPosView.y - 81;
[moveView setToValue:[NSValue valueWithCGPoint:destView]];
}
// Animate the view
[[entirePage layer] addAnimation:moveView forKey:#"move"];
// Set the final position of our layer
[[entirePage layer] setPosition:destView];
menuDisplayed = !menuDisplayed;
And then in the animationDidStop method:
CGPoint currentPosMenu = [[menuBar layer] position];
if (menuDisplayed) {
currentPosMenu.x -= 81;
} else {
currentPosMenu.x += 81;
}
[[menuBar layer] setPosition:currentPosMenu];
Help???
You shouldn't need to mess with the layers. You could probably achieve the effect you want by laying out the views in Interface Builder at the positions they will be in after they are animated into view. In other words, first lay things out in their final/correct positions. Don't do anything funky in IB.
In your code, after the app is launched or in a -viewDidAppear: method if you're using a UIViewController, you could offset the views by some amount and then restore them to their original position in an animation block:
myView.transform = CGAffineTransformMakeTranslation(0,81);
[UIView beginAnimations:#"slideUp" context:nil];
myView.transform = CGAffineTransformIdentity;
[UIView commitAnimations];
As for the lack of user interaction on your views, that could be a number of things. If all of your views are subviews of something like a UIImageView, UIImageView has userInteractionEnabled set to NO by default (at least if you build one in code - I'm not sure off hand what IB's default settings are for an image view). It could also mean that the superview of your views is actually too small and its frame does not contain the subviews. (If clipping was turned on for the superview, you wouldn't even be able to see subviews that are having this particular problem.)
EDIT:
I read things more carefully and see you want things to move in response to a button press, so in other words the views will need to be hidden from the start. In that case you could still lay everything out in IB in their final position, but just set them as hidden in IB. When you push the button, set the views visible (hidden=NO) before translating them. That should allow them to be laid out in their final/correct place in IB making sure that they are positioned on the proper superviews, etc while still getting the animation effect you want.
Forget about the animations for now; you should move your view by setting its frame property.
E.g.:
CGRect menuFrame = entirePage.frame;
if (menuDisplayed)
{
menuFrame.origin.x += 81;
}
else
{
menuFrame.origin.x -= 81;
}
entirePage.frame = menuFrame;
// Do your animation here, after the view has been moved
Don't worry about the animation until you've verified that your view is being placed in the correct location. Once you've verified that that code is working correctly, then do your animation after you set the frame property.
Note that you probably don't need to use the CoreAnimation API at all, unless you're doing something complex. UIKit can do animation on its own. E.g:
[UIView beginAnimations:#"MyAnimation" context:NULL];
myFirstView.frame = ...;
myOtherView.frame = ...;
[UIView commitAnimations];

Animation is slow on iPhone

I'm developing an app that would display images and change them according to the user's action. I've created a subclass of UIView to contain an image, an index number and an array of image names. The code is like this:
#interface CustomPic : UIView {
UIImageView *pic;
NSInteger index;
NSMutableArray *picNames; //<-- an array of NSString
}
And in the implementation part, it has a method to change the image using a dissolve effect.
- (void)nextPic {
index++;
if (index >= [picNames count]) {
index = 0;
}
UIImageView *temp = pic;
pic.image = [UIImage imageNamed:[picNames objectAtIndex:index]];
temp.alpha = 0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:0.25];
pic.alpha = 0;
temp.alpha = 1;
[UIView commitAnimations];
}
In the viewController, there are several CustomPic which would change the images depends on users' choice. The images would change as expected with the fade in/out effect, but the animation performance is really bad. I've tested it on an iPhone 3G, the Instruments shows that the animation is only 2-3FPS! I tried many methods to simplify and modify the codes but with no hope. Is there something wrong in my code or in my concept? Thanks for any help.
P.S. all the images are 320*480 PNGs with a max size of 15KB.
In that code snippet you are only using one UIImageView:
UIImageView *temp = pic;
So this line does nothing:
pic.alpha = 0;
To fade one image in and another image out, you need two instances of UIImageView.
To speed things up, you might want to load the next image ahead of time. Set a delegate for the animation, and when it completes load the image that will be displayed in the next call of nextPic.
Edit:
If the images are not transparent, try setting the pic.opaque = YES; so the view can ignore underlying views. If that is not an option, try having as few views as possible between the fading view and a full screen opaque view. At each step of the fade, the view must be composited with every underlying view until an opaque view is found.
If you have many transparent views under the fade, consider making a temporary composite of them all, the equivalent of flatten layers in photoshop, and placing the composite as an image in a full screen opaque view before starting the fade. It may delay starting the fade a moment, but the fade itself should be smoother.
Are you running iPhone OS 4 beta? I find the beta OS much slower on the older generation devices like iphone 3g
Try change
[UIView setAnimationDuration:0.25];
to
[UIView setAnimationDuration:0.025];
and see if that's something you are looking for...
With an animation duration of .25 of a second, you can be guaranteed to get < 4 FPS. What FPS are you targeting?