Animating the UIButton Layer? - objective-c

I'm trying to bring the ripple effect seen in the dashboard application to iphone. My idea is whenever i place a button in the layout view there should be ripple effect around the button.
However, I`m able to bring the ripple effect for the whole view but I needs the effect only around the button. I don know where I went wrong. I tried the following code.
LayoutButton *tempLayoutButton=[[LayoutButton alloc] initWithObject:object];
tempLayoutButton.center=copyImage.center;
[layoutView addSubview:tempLayoutButton];
CALayer *templayer=[CALayer layer];
tempLayoutButton.layer.masksToBounds=NO;
templayer.frame=CGRectMake(0,0,50,50);
[tempLayoutButton.layer addSublayer:templayer];
CATransition *animation = [CATransition animation];
animation.delegate = self;
animation.duration = 1.0f;
animation.timingFunction = UIViewAnimationCurveEaseInOut;
animation.type = #"rippleEffect";
[templayer addAnimation:animation forKey:#"animation"];
[tempLayoutButton release];
[tempLayoutButton.layer addSublayer:templayer];
If I replace templayer with LayoutView layer I can see the riple effect from the whole view. Can anyone tell me the solution
Thanks in advance

I found the answer in one of apples mailing list. The animation is apple`s own animation and no one can use that. And there is no guarantee for the animation to appear properly in the screen. If we need the same type of animation we need to manipulate the layers and get the animation

Related

CATransition push without fade

I'm making a navigation controller class for Mac OS X.
I want to replace the current view with a kCATransitionPush animation.
Like in this post:
Core Animation Tutorial - Wizard Dialog With Transitions
The CATransition is set up like this:
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.view setAnimations:#{ #"subviews" : transition }];
However, when I replace the views, there is a fade animation, which is being automatically added.
[NSAnimationContext beginGrouping];
{
[[self.view animator] replaceSubview:_currentViewController.view with:newViewController.view];
}
[NSAnimationContext endGrouping];
How can I do a push animation without the fading?
The best way I've found to get smooth Core Animation transitions that works regardless of whether the view supports CA or not is to do the following:
Create an image of the view you are trying to animate, using NSView -cacheDisplayInRect:toBitmapImageRep or a similar method
Put that image in an NSImageView
Layer back the image view, which will draw fine without glitches when layer backed
Add the image view as a subview over the view that you are trying to transition
Animate the image view frame using NSView's animator proxy
Remove the image view once the animation has completed
I suspect you're running into implicit animations - Core Animation will automatically animate layer property changes that happen outside of your own transactions.
There's a good summary of several methods for disabling these implicit animations in these two questions:
How to disable CALayer implicit animations?
Disabling implicit animations in -[CALayer setNeedsDisplayInRect:]
...and you can read more about implicit transactions in the Core Animation docs
I think the transition from left transition includes a built-in fade. The IOS push transitions do.
If you don't want that, you might have to roll your own push transition using Core Animation. This would be easy in iOS with UIView animations. Sadly, there is not an equivalent in Mac OS. I wish Apple would go back and add view animations to Mac OS. I get spoiled using them in iOS, and then miss them when I work on Mac applications.
Add below code
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[transition setDuration:0.5];
[self.view.layer addAnimation:transition forKey:kCATransition];

Animating label (NSTextField) horizontally

I have a NSTextField as a label, showing a string.
I want to animate this label from right to left, if the content of it is too large to be displayed at once.
I've done this with an NSTimer so far, it works, but it's just not a very good solution.
The labels are displayed in an NSTextFieldCell, in a Table View.
They often get out of sync, and I guess it's just eating up a lot of CPU/GPU resources.
Is there another way with Core Animation to do this?
I have tried it with layers, as you can see right here:
CALayer and drawRect
but I didn't get it working either.
I would really appreciate your help.
You can simply animate the position of NSTextField with animator like
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
you can also embed it in "CATrancation" code like this:
[CATransaction begin];
[CATransaction setAnimationDuration:0.5];
[CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
[CATransaction commit];
if you need animation delegate, you can use CABasicAnimation
CABasicAnimation* animation = [CABasicAnimation animation];
animation.delegate = self;
NSDictionary *animations = [NSDictionary dictionaryWithObjectsAndKeys:animation,#"frameOrigin",nil];
[textField setAnimations:animations];
[[textField animator] setFrameOrigin:NSMakePoint(x,y)];
Delegate methods are
- (void)animationDidStart:(CAAnimation *)theAnimation;
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag;
If you need to mask your text field, just embed it in other NSView.
First, animate the label using one of the functions offered in the other answers.
Then, if you want to display another view on the sides without overlapping, you can:
Insert the label in a subview with the limits you wish
Use bringSubviewtoFront: or sendSubviewToBack: to make sure your label stays in the back

CALayer fade from current value

My app uses CALayer to draw views. More precisely, it uses the drawLayer:inContext: method on a sublayer of a UIView's top layer. This is a nice way to get the 'implicit' animation of consecutive drawLayer:inContext: drawings to fade into each other over time. The fading animations happen fairly fast, maybe in 0.25 seconds, but to change its duration, simply implement another delegate method called actionForLayer:forKey:. In this perfectly working example implementation here the default duration is stretched to 2.0 seconds:
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event];
animation.duration = 2.0;
return animation;
// or return nil for the default duration.
}
On to the issue at hand.
If you call [sublayer setNeedsDisplay] faster than the fades have time to complete, with each new fade you'll see a sudden jump. From the looks of it, the fade that's in progress is cancelled and it's final state is used as the starting point of the new fade. This might not be very surprising, but the visual result is rather unwanted.
Consider the scenario of a ten second fade from black to white, with another fade, to black, triggered five seconds after the start. The animation will start fading from black to white, but when it's at a 'half way gray' it jumps to full white before fading to black again.
Is there a way to prevent this from happening? Can I get the layer to fade from the gray back down to black? Is there a CALayer drawing equivalent of saying UIViewAnimationOptionBeginFromCurrentState (used in UIView animations)?
Cheers.
A layer's animation is only a visual representation of what the layer should look like as it animates. In CA when you animate from one state to another, the entire state of the layer changes immediately. A presentation layer is created and displays the animation, and when the animation completes the actual layer is left in place at the end.
So, my guess is that when you want to transition from one state to another, and the current animation hasn't completed yet, you have to capture the current state of the animation and then use this as the starting point for your next animation.
The problem lies in not being able to modify a layer's current animation.
In the following post I capture the current state of an animation, set that as the current state for the layer and use that as the beginning value from which to animate. The post applies this technique to the speed / duration of an animation, but can also be applied to your scenario.
https://stackoverflow.com/a/9544674/1218605
I'm a little stumped on this one too.
Did you forget to specify the fillMode kCAFillModeForwards. There's more info about that in the reference docs.
For example, I got this to work without any snapping, although I'm not changing the duration.
#implementation FadingLayer
- (void)fadeOut {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"backgroundColor"];
animation.fillMode = kCAFillModeForwards;
animation.fromValue = (id)[UIColor redColor].CGColor;
animation.toValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[self addAnimation:animation
forKey:#"test"];
}
- (void)fadeIn {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"backgroundColor"];
animation.fillMode = kCAFillModeForwards;
animation.fromValue = (id)[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.0].CGColor;
animation.toValue = (id)[UIColor redColor].CGColor;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[self addAnimation:animation
forKey:#"test"];
}
#end
You'll probably want to animate a custom property however.
Hope this helps :/
I wanted to accomplish the same thing with a zoom animation of a layer tree. I have a zoom in/out key-equivalent where the user can zoom the layer tree accordingly. However, if the user presses the zoom key-equivalent in rapid succession, there would be a temporary snap-back to the values prior to the onset of the animation, since the previous animation hadn't yet completed.
At the end of the animation code, performing a sole [CATransaction commit] forced any pending transactions to be committed to the layer model before the start of the next animation, and solved the problem.
The documentation says:
+ commit
Commit all changes made during the current transaction.
Declaration
+ (void)commit
Special Considerations
Raises an exception if no current transaction exists.
However, testing this with many [CATransaction commit] messages in succession doesn't actually raise an exception. I've used this same technique to squelch warnings of the form:
CoreAnimation: warning, deleted thread with uncommitted
CATransaction;
in an NSOperation whose thread of execution finishes before layer animations do. It could be that Apple changed this behaviour in recent OS releases to a no-op (which would be much saner) if no current transaction exists, without updating the documentation.

How to animate and rotate an image?

Hi i am working on an iPhone application and i have to animate and rotate an image, Image is attached here
now purpose of this image is that whenever any tap some where on iPad it will animate and will point towards that place.
Please help me to figure it out. Thanx
Try this -
CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:#"transform.rotation.z"];
animation.fromValue = [NSNumber numberWithFloat:0.0f];
animation.toValue = [NSNumber numberWithFloat: 2*M_PI];
animation.duration = 10.0f;
animation.repeatCount = INFINITY;
[self.yourImage.layer addAnimation:animation forKey:#"SpinAnimation"];
check this tutorial. It will really help you.
To animate images view, you'll need to use CoreAnimation.
All you have to do is making UIImageView object with your image inside and then you'll manipulate directly the layer to animate.
There is 2 kind of animation with core animation :
Implicit animation (normally they are activate by default) : Everytime you change some setting on the layer (like position with [imageView.layer setPosition:CGPointMake...]) there should be an implicit animation with default parameters (Duration, AnimationCurve etc.)
Explicit animation : If you want to create more complex animations, you should use explicit animation, it will allow you to do complex things like moving, rotating and scaling some layer in the same time.
I encourage you to check the core animation programming guide

Animate setContent of an NSWindow

In the past I've been successfully able to fade in an NSWindow using the following code;
if (![statusWindow isVisible])
{
statusWindow.alphaValue = 0.0;
[statusWindow.animator setAlphaValue:1.0];
}
CAAnimation *anim = [CABasicAnimation animation];
[anim setDelegate:self];
[statusWindow setAnimations:[NSDictionary dictionaryWithObject:anim forKey:#"alphaValue"]];
[statusWindow makeKeyAndOrderFront:self];
For my current project I'm trying to make a flash similar to the one in Photo Booth. I've created a white NSPanel and was planning to set my NSWindow's content to the panel, and quickly set it back.
Is it possible to set the contentView of an NSWindow using a nice fade effect?
P.S - If there is an easier way you know of how to achieve the flash, please tell me!
Thanks in advance,
Ricky.
Why use another window? It looks like you're trying to use CoreAnimation already so why not just add a white CALayer to your existing view and animate its opacity?