fade View IN and OUT - ios

Good Morning everyone,
I'm totally confused with this problem.
I have 3 UIWebViews and what should hapen is webView1 fades in (that works) fades out und WebView2 fades in......
I made it so far with:
CATransition *Animation = [CATransition animation];
[Animation setDuration:4.0];
[Animation setType:kCATransitionFade];
[Animation setSubtype:kCATransitionFade];
[Animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
transitioning = YES;
if (transitioning) {
[self.webView1.layer addAnimation:Animation forKey:nil];
self.webView1.hidden = YES;
self.webView2.hidden = NO;
can anyone help me with that?
And when it fades in the webView fades from white even the background color is set to an other color!
can't I effect the color?

You should use UIView implicit animations. For instance, a cross fade from webView1 to webView2:
[UIView beginAnimations:#"fade" context:nil];
self.webView1.alpha = 0.0;
self.webView2.alpha = 1.0;
[UIView commitAnimations];
If you wanna execute some code after the animation finished, insert this between begin and commit:
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(fadeAnimationDidStop:finished:context:)];
and create the didStop method with the signature
- (void)fadeAnimationDidStop:(NSString*)animationID finished:(NSNumber*)finished context:(void*)context`

transition.type =kCATransitionMoveIn;
transition.subtype =kCATransitionFade;

Related

iphone - undo or reverse kCATransitionPush to send image off screen

I am currently sliding in an animated image from the right of the screen using CATransition:
CATransition *transition = [CATransition animation];
transition.duration = TRANSITION_DURATION;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
[self.layer addAnimation:transition forKey:nil];
self.image = [UIImage animatedImageNamed:prefix duration:ANIMATION_DURATION];
My question is, how do I slide the image out? Once the image animation cycles through, I want to send it off the screen in the direction from whence it came, i.e. TransitionToRight, but there doesn't seem to be such a transition type. Please suggest how I might accomplish this reverse transition.
Here is how I might write it, if such a reverse transition existed:
[self performSelector:#selector(removeAnimatedImage) withObject:nil afterDelay:ANIMATION_DURATION];
and inside removeAnimatedImage, I would create another CATransition animation with this reverse direction to send it off the screen.
Did you try the kCATransitionFromLeft version of the push transition? It should be the inverse of FromRight.
Not the ideal solution, but one hack is to either animate a change in frame bounds, or applying a translation transform animation:
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:TRANSITION_DURATION];
if (enteredFromRight) {
self.transform = CGAffineTransformMakeTranslation(SCREEN_SPACE_WIDTH, 0);
} else {
self.transform = CGAffineTransformMakeTranslation(-SCREEN_SPACE_WIDTH, 0);
}
[UIView commitAnimations];

Flipping the UILabel

I want to use the CABasicAnimation to flip the UILabel. Animation will repeat forever and will change the text of UILabel between two different values.
- (void)animateLabel
{
[self.myLabel.layer addAdnimation:[self labelAnimation] forKey:#"flip"];
}
- (CAAnimation*)labelAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
[animation setRepeatCount:NSIntegerMax];
[animation setAutoreverses:YES];
[animation setDuration:2.0];
[animation setDelegate:self];
CATransform3D transform = CATransform3DMakeRotation(M_PI_2, 1, 0, 0);
[animation setToValue:[NSValue valueWithCATransform3D:transform]];
return animation;
}
Now, I tried using the delegate but the delegate method is only when the animation first begins. Rather I need to be able to know the the label completes one cycle. Is there some convenience method or way to do it with CALayer or do I have to use CADisplay link or timer ? I would like to thank you before hand for helping me.
To get notified on each cycle, setRepeatsCount to 1. You'll then get notified in the delegate animationDidStop:finished. You would then simply add the same animation again.
- (void)animateLabel
{
[self.myLabel.layer addAdnimation:[self labelAnimation] forKey:#"flip"];
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
[self animateLabel];
// do other stuff
}
- (CAAnimation*)labelAnimation
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
[animation setRepeatCount:1];
[animation setAutoreverses:YES];
[animation setDuration:2.0];
[animation setDelegate:self];
CATransform3D transform = CATransform3DMakeRotation(M_PI_2, 1, 0, 0);
[animation setToValue:[NSValue valueWithCATransform3D:transform]];
return animation;
}
No, this is the way you're supposed to do it according to the documentation.
Setting this property to HUGE_VALF will cause the animation to repeat forever.

Animate UIView using Core Animation?

I am having a little trouble getting a UiView to animate properly using core animation. Here is my code:
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"position"];
[animation setFromValue:[NSValue valueWithCGPoint:self.view.layer.position]];
[animation setToValue:[NSValue valueWithCGPoint:CGPointMake(250, self.view.layer.position.y)]]; //I want to move my UIView 250 pts to the right
[animation setDuration:1];
[animation setDelegate:self]; //where self is the view controller of the view I want to animate
[animation setRemovedOnCompletion:NO];
[self.view.layer addAnimation:animation forKey:#"toggleMenu"]; //where self.view returns the view I want to animate
I have also implemented the following delegate method:
-(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
if(flag)
[self.view.layer setTransform:CATransform3DMakeTranslation(250, 0, 0)]; //set layer to its final position
}
I am trying to make it so that the UIView moves 250 points to the right. However, when the animation is triggered, my view starts to move but the animations seems to end before the view moves 250 points to the right, resulting in the UIView 'teleporting' to its final position. I can't seem to figure out what is causing this behavior.
I have also tried using the UIView method +(void)animateWithDuration:animations: and this approach works perfectly. However, I am trying to achieve a subtle 'bounce' effect and I'd much rather achieve it using the setTimingFunction:functionWithControlPoints: method rather than having multiple callbacks.
Any help and suggestions are appreciated.
Try like this
CABasicAnimation *rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:#"position"];
rotationAnimation.fromValue=[NSValue valueWithCGPoint:CGPointMake([view center].x, [view center].y)];
rotationAnimation.toValue=[NSValue valueWithCGPoint:CGPointMake([view center].x+250, [view center].y)];
rotationAnimation.duration = 1.0+i;
rotationAnimation.speed = 3.0;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1.0;
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
[view.layer addAnimation:rotationAnimation forKey:#"position"];
If you are aiming to move your view, your code should go like this:
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"position"];
[animation setFromValue:[NSValue valueWithCGPoint:self.view.layer.position]];
CGPoint p = self.view.layer.position;
p.x += 250;
self.view.layer.position = p;
[animation setDuration:1];
[animation setRemovedOnCompletion:NO];
[self.view.layer addAnimation:animation forKey:#"toggleMenu"];
You should really change your view's(layer's) position. Otherwise, your view will stay still at its previous position when your animation removed. That's a difference between UIView Animation and Core Animation.
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"position"];
[animation setFromValue:[NSValue valueWithCGPoint:view.layer.position]];
CGPoint newPosition = CGPointMake(200, 300);
view.layer.position = p;
[animation setDuration:0.5f];
[animation setRemovedOnCompletion:NO];
[group setFillMode:kCAFillModeForwards];
[[view layer] addAnimation:animation forKey:#"position"];

Fade-transition a rect in a UIView

So I want to redraw a rectangle in a view and then transition to it with a fade. This is what I'm using now:
[self setNeedsDisplayInRect:changedRect];
CATransition *animation = [CATransition animation];
[animation setDuration:0.25];
[animation setType:kCATransitionFade];
[[self layer] addAnimation:animation forKey:nil];
This however fades the entire layer. How can I go about fading just changedRect?
Thanks,
Alec

Animate between two states of a view, using custom animation

I would like to animate between two states of a view. Say, for example, I have a view with a label and when I change the text of the label an animation renders that change as a page flipping.
Now you can of course do this with a [UIView setAnimationTransition:forView:cache:]:
- (IBAction)nextPage {
[UIView beginAnimation:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:pageView cache:NO];
label.text = #"page 2";
[UIView commitAnimations];
}
- (IBAction)previousPage {
[UIView beginAnimation:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:pageView cache:NO];
label.text = #"page 1";
[UIView commitAnimations];
}
...but then you cannot use your own custom animation, you are stuck to the built-in animations (they're nice but they're not tailored to my needs).
So the other option is to add a CAAnimation to the view's layer:
- (IBAction)nextPage {
CAAnimation *animation = [self animationWithDuration:1 forward:NO];
[pageView.layer addAnimation:animation forKey:#"pageTransition"];
label.text = #"page 2";
}
- (IBAction)previousPage {
CAAnimation *animation = [self animationWithDuration:1 forward:YES];
[pageView.layer addAnimation:animation forKey:#"pageTransition"];
label.text = #"page 1";
}
Then you are free to set whatever animation Core Animation enables you to do. This works well if I define a CATransition animation, for example a kCATransitionReveal: a view in the "page 2" state appears below the view in the "page 1" state as it slips out.
- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward {
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionReveal];
[animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
animation.duration = duration;
return animation;
}
But when I define the animation to be for example a CABasicAnimation, only one state of the view is visible.
- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward {
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -1000;
transform = CATransform3DRotate(transform, M_PI, 0.0f, 1.0f, 0.0f);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
if(forward) {
animation.fromValue = [NSValue valueWithCATransform3D:transform];
} else {
animation.toValue = [NSValue valueWithCATransform3D:transform];
}
animation.duration = duration;
return animation;
}
Instead, I would like the view in the "page 1" state to remain visible until the end of the animation while the view in the "page 2" state comes into frame, exactly as it behaves with a transition animation.
Of course, I could always mess with duplicating the view and having one appear as a sibling view while I animate the frontmost one and remove it from superview on completion... but there must be a much more straight way to achieve this rather simple animation effect without messing with the views.
Probably something to tell the layer, but then I don't know what, and that's where I need your help, guys :)
Thanks!
I recently did a custom slide transition between subviews in a controller. My approach was to grab a bitmap of the view-out and the view-in, add them to a view and animate that view. At the end you can just remove the transition view and show the view-in. Here's a snippet the transition method:
-(void) transitionToView:(UIView *)viewIn lastView:(UIView *)viewOut slideRight:(BOOL)isRight {
UIGraphicsBeginImageContext(viewOut.frame.size);
UIImageView *bitmapOut = [[UIImageView alloc] initWithFrame: viewOut.frame];
[viewOut.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewOutImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
bitmapOut.image = viewOutImage;
UIImageView *bitmapIn = [[UIImageView alloc] initWithFrame: viewIn.frame ];
bitmapIn.frame = CGRectMake(isRight ? 320 : -320, bitmapIn.frame.origin.y, bitmapIn.frame.size.width, bitmapIn.frame.size.height);
UIGraphicsBeginImageContext(viewIn.frame.size);
[viewIn.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewInImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
bitmapIn.image = viewInImage;
[self.view addSubview:transitionContainer];
[transitionContainer addSubview:bitmapIn];
[transitionContainer addSubview:bitmapOut];
[self removeAllViews];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(swapViewsAtEndOfTransition:)];
transitionContainer.frame = CGRectMake(isRight ? -320 : 320, 0, 640, 411);
[UIView commitAnimations];
[bitmapOut release]; bitmapOut = nil;
[bitmapIn release]; bitmapIn = nil;}
Then, in the swapViewsAtEndOfTransition selector you can update the views accordingly.
Well, you can create a layer, set it content to an image representing your view final state, than apply the animation to this layer. When the animation is done you can remove the layer and switch view state.
I think this will work better than instancing whole view.
Years have passed but I guess I found a solution for you. Just use kCATransitionPush instead of kCATransitionReveal. Like this:
- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward {
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
animation.duration = duration;
return animation;
}

Resources