UIView animation to move and back - objective-c

I would like to have animation on a view, that it will go 2 pixels right on x, and 2 pixels back left on x .
I have this for opacity, and i am looking to adjust this to make it ,
CABasicAnimation *theAnimation;
theAnimation=[CABasicAnimation animationWithKeyPath:#"opacity"];
theAnimation.duration=1.0;
theAnimation.repeatCount=HUGE_VALF;
theAnimation.autoreverses=YES;
theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
theAnimation.toValue=[NSNumber numberWithFloat:0.3];
[image.layer addAnimation:theAnimation forKey:#"animateOpacity"];

If you just want the animation to occur once then you can jump up a few levels of abstraction and use the block based view animations
[UIView animateWithDuration:1.f
delay:0
options:UIViewAnimationOptionAutoreverse
animations:^{
view.transform = CGAffineTransformMakeTranslation(2.f, 0.f);
} completion:^(BOOL finished) {
view.transform = CGAffineTransformIdentity;
}];
This applies a translation of two points right and then removes it on completion

Related

Scaling UIView using transform after animating frame change causes UIView to jump back to original frame before scaling

I'm trying to scale a UIView (with animation) after I move it (with animation). The problem is, when the scaling animation begins, it jumps back to the original position. Why?
[UIView animateWithDuration:t delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
// Drop the ball
CGRect frame = coinView.frame;
frame.origin.y += d;
coinView.frame = frame;
coinView.shouldSparkle = NO;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
// Initial scale up for ball "poof"
coinView.transform = CGAffineTransformScale(coinView.transform, 1.5, 1.5);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.3 animations:^{
coinView.transform = CGAffineTransformScale(coinView.transform, 0.000001, 0.000001);
} completion:^(BOOL finished) {
[coinView removeFromSuperview];
}];
}];
}];
EDIT: This is how I generated my d:
static CGFloat groundPositionY = 325;
CGRect convertedFrame = [coinView.superview convertRect:coinView.frame toView:self.view];
CGFloat d = groundPositionY - CGRectGetMaxY(convertedFrame);
EDIT2: Okay, so I changed the second UIView animation to the following and I discovered that the jump (and the scale down) happens before the second animation occurs, i.e. when animateWithDuration:delay:options:animations:completion: is called.
[UIView animateWithDuration:5 delay:3 options:0 animations:^{
coinView.transform = CGAffineTransformScale(coinView.transform, 1.5, 1.5);
} completion:nil];
I tested your code and it works fine for me. How do you generate your d? and on which block exactly it goes back?
I found the problem...
The coinView is a subview of a child view controller's view. The problem comes from the fact that I overrode that child view controller's viewDidLayoutSubviews method to lay out all the coinView's, so whenever that method was called, the coin view would move back to its original position and size intended by the child view controller.
Thanks for all of your help, repoguy and sergio!!

iOS view transform animation

I'm probably missing something simple, but trying to do a simple "Ken Burns Effect" with an image view.
First the code:
[UIView animateWithDuration:20
delay:2
options:UIViewAnimationCurveLinear
animations:^{
CGAffineTransform move = CGAffineTransformMakeTranslation(40, 40);
CGAffineTransform zoom = CGAffineTransformMakeScale(1.2, 1.2);
CGAffineTransform transform = CGAffineTransformConcat(zoom, move);
self.imageView.transform = transform;
}
completion:^(BOOL finished){
NSLog(#"Done");
}];
I expected this to start with the image view at normal scale and expand it to 120% of the size over 20 seconds. What actually happens is that it starts out immediately smaller than normal size, then expands to normal size.
If I use the reciprocal of the scale value, it starts out zoomed in and then zooms out to normal scale which is the opposite of the effect I want.
Any ideas?
Ok, this actually worked and does what I want.
CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:#"transform"];
transformAnimation.duration = 20.0;
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
transformAnimation.removedOnCompletion = NO;
transformAnimation.fillMode = kCAFillModeForwards;
CATransform3D xform = CATransform3DIdentity;
xform = CATransform3DScale(xform, 1.2, 1.2, 1.0);
xform = CATransform3DTranslate(xform, 60, -60, 0);
transformAnimation.toValue = [NSValue valueWithCATransform3D:xform];
[self.imageView.layer addAnimation:transformAnimation forKey:#"transformAnimation"];
It sounds like the view is being re-laid out by its parent view in response to the change in transform, casing it to be scaled down to the end result of the transform as soon as the transform is set in the animation block. The key is that your first attempt makes changes directly to the view, while the second approach works with the layer.
Have you try starting form the current transform of your imageView ?
[UIView animateWithDuration:20
delay:2
options:UIViewAnimationCurveLinear
animations:^{
CGAffineTransform trans = self.imageView.transform;
CGAffineTransformTranslate(trans, 40, 40);
CGAffineTransformScale(trans, 1.2, 1.2);
self.imageView.transform = trans;
}
completion:^(BOOL finished){
NSLog(#"Done");
}];

Hide and show scrollview with animation

In my app I have a scrollview and when I press a button it is hidden when I press again it shows up.
I use scrollview.hidden = YES (or NO) to do it.
But I want to do it with an animation. For example, it may disappear from the bottom of the screen by moving and shows up with the same way. How can I do that?
edit:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = bottomScroller.frame;
if(Frame.origin.y == 380){
Frame.origin.y = 460;
}else{
Frame.origin.y = 380;
}
bottomScroller.frame = Frame;
[UIView commitAnimations];
This solved my problem...
You may check UIView animations. It's pretty easy. For example to animate translation you may use something like:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 0;
yourView.frame = Frame;
[UIView commitAnimations];
Then to move it back:
[UIView beginAnimations:#"myAnimation" context:nil];
CGRect Frame = yourView.frame;
Frame.origin.y = 100;
yourView.frame = Frame;
[UIView commitAnimations];
Changes in frame, alpha and some other parameters will be automatically animated.
You can use animations like so:-
[UIView animateWithDuration:2.0 animations:^{
[scrollview setframe:CGRectMake(xpos, ypos, width, height)];
}];
If you want to slide the scrollview on or off the screen set its y position - the bottom of the view is you want to hide it, the normal y position if you want to show it.
The 2.0 is an animation length, this can be changed to whatever you need it to be!
You can do this by using simple view animations. Here's an example of how you might do this:
// myScrollView is your scroll view
-(void)toggleShow{
CGFloat targetAlpha = myScrollView.alpha == 1 ? 0 : 1;
CGFloat yPosition = targetAlpha == 1 ? 0 : self.view.frame.size.height;
[UIView animateWithDuration:1.0 animations:^{
myScrollView.frame = CGRectMake(myScrollView.frame.origin.x, yPosition, myScrollView.frame.size.width, myScrollView.frame.size.height);
myScrollView.alpha = targetAlpha;
}];
}
targetAlpha will always be the opposite of the current state (1 or 0), and if it's 0 then the y position will be set to the bottom of the parent view. Using the new-school UIView animations API with blocks we can execute these changes to the scroll view over 1 second (in my example).
ScrollView appers from down side of screen with animation. I think this up-animation is what you want.
// ScrollView appearing animation
- (void)ScrollViewUpAnimation
{
// put the scroll view out of screen
CGRect frame = ScrollView.frame;
[self.view addSubview:ScrollView];
ScrollView.frame = CGRectMake(0, 460, frame.size.width, frame.size.height);
// setting for animation
CGPoint fromPt = ScrollView.layer.position;
CGPoint toPt = CGPointMake(fromPt.x, fromPt.y - frame.size.height - 44);
CABasicAnimation* anime =
[CABasicAnimation animationWithKeyPath:#"position"];
anime.duration = 0.2;
anime.fromValue = [NSValue valueWithCGPoint:fromPt];
anime.toValue = [NSValue valueWithCGPoint:toPt];
// change the position of Scroll View when animation start
[ScrollView.layer addAnimation:anime forKey:#"animatePosition"];
ScrollView.layer.position = toPt;
}

Animate Rotation/Scale/Translate of UIImage at the same time

I am new to objective-c and I want to add an image to the screen, tweening it like in AS3, moving it from one end to the other of the screen while rotating around its own center point.
I tried with
[UIView animateWithDuration:0.5 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
// TRANSFORM SCREENSHOT
screenShotView.transform = CGAffineTransformRotate(screenShotView.transform, -M_PI * 0.05);
screenShotView.transform = CGAffineTransformScale(screenShotView.transform, 0.6, 0.6);
screenShotView.transform = CGAffineTransformTranslate(screenShotView.transform,
self.webView.frame.origin.x,
self.webView.frame.origin.y - self.webView.frame.size.height * 0.3
);
but with this code the image rotates around the center of the TransformIdentity. So while rotating and moving the rotation gets out of controll and the image isn't exactly at the position I loved it to be.
What is the right way to rotate and translate at the same time, translating the rotation center with the image?
and at least after transformation I want to add a close button to the right upper corner of the image. for that I need the new coordinates of the corner, too.
thnx!
I now ended with the following code, but I still don't know if this is the state of the art solution.
CGAffineTransform translate = CGAffineTransformMakeTranslation(self.webView.frame.origin.x,self.webView.frame.origin.y - self.webView.frame.size.height * 0.25);
CGAffineTransform scale = CGAffineTransformMakeScale(0.6, 0.6);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
transform = CGAffineTransformRotate(transform, degreesToRadians(-10));
[UIView beginAnimations:#"MoveAndRotateAnimation" context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:2.0];
screenShotView.transform = transform;
[UIView commitAnimations];
IOS 7's preferred way to do this would be using a block object. It has several advantages compared to the 'older' way of animating. Especially that it can make use of multi-core and video co-processing. Also the 'built-in' call back part (the completion part) is very useful, as it keeps any necessary state information and links to objects as needed.
CGAffineTransform translate = CGAffineTransformMakeTranslation(self.webView.frame.origin.x,self.webView.frame.origin.y - self.webView.frame.size.height * 0.25);
CGAffineTransform scale = CGAffineTransformMakeScale(0.6, 0.6);
CGAffineTransform transform = CGAffineTransformConcat(translate, scale);
transform = CGAffineTransformRotate(transform, degreesToRadians(-10));
// animation using block code
[UIView animateWithDuration:2.0
delay:0.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
screenShotView.transform = transform;
}completion:^(BOOL finished){
// do something if needed
}];

Drop Down UIView With Buttons

Okay, so I want to make a menu that expands down at the current touch location. I achieve this by adding my menuView with a height of 1 and then changing the height to my desired one like this:
[UIView beginAnimations:NULL context:nil];
CGRect fullRect;
fullRect = CGRectMake(menuView.frame.origin.x, menuView.frame.origin.y, 290, 180);
menuView.frame = fullRect;
[UIView commitAnimations];
Now the problem is that there are 4 buttons in this menuView and these buttons appear first and then the menuView expands down under them. Any ideas how to make the buttons appear with the menuView and not before it?
You have to set menuView.clipsToBounds = YES so the buttons are not shown outside the bounds of your menuView while it is expanding.
I would also add the following to have a fade-in effect for your buttons.
button1.alpha = 0.0; // Do this for each button before the [UIView beginAnimations];
button1.alpha = 1.0; // Do this during the animation block.
I would use a Block animation instead. That way, you can make the buttons appear during or after the animation easily. Try something like:
[UIView animateWithDuration:1.0
animations:^{
CGRect newRect = menuView.frame;
menuView.size.height += 289;
menuView.frame = newRect;
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.1
animations:^{
button.hidden = NO;
}
completion:^(BOOL finished){
;
}];
}];
This will make the button stop hiding at the end of the animation. Of course, you could add more blocks in the completion block to handle more animations, and it is easy to customize this. Hope that helps!