Blinking NSButton with Core Animation - core-animation

I've got an NSButton called _indicatorButton with a PNG image (basically a green LED light as PNG set with setImage:) without border and text. I'm trying to make it "flash" with the following code:
- (void)animateButton
{
NSLog(#"Animating…");
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"opacity"];
[animation setFromValue:[NSNumber numberWithFloat:1.0]];
[animation setToValue:[NSNumber numberWithFloat:0.0]];
[animation setDuration:0.3f];
[animation setTimingFunction:[CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[animation setAutoreverses:YES];
[animation setRepeatCount:20000];
[_indicatorButton.layer addAnimation:animation forKey:#"opacity"];
}
…but nothing happens. The method gets called and the link in the XIB is OK, since changing the image on the button programmatically works fine.
Any hints why it doesn't blink at all?

For backwards compatibility, views on OS X don't use Core Animation layers as their backing store by default. The reason nothing is happening is likely that layer of your button is nil.
You can tell your view that it should be layer-backed using myView.wantsLayer = YES;. Please read the documentation for wantsLayer.

Related

How to update UIView background smoothly

in my app I want to change the background of an uiview based on camera, All works properly but the problem is the background is changed too sharply (I think because of the focus).
So there's a way to change the background color of a UIView smoothly?
I actually use this code:
dispatch_async(dispatch_get_main_queue(), ^ {
[myview setBackgroundColor:[UIColor colorWithRed:red green:green blue:blue alpha:1]];
});
The UIVIew animation solution doesn't work beacause the changes are too fast.
Just before setting the background colour do something like;
CATransition *transitionAnimation = [CATransition animation];
[transitionAnimation setType:kCATransitionFade];
[transitionAnimation setDuration:0.2f];
[transitionAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[transitionAnimation setFillMode:kCAFillModeBoth];
[myview layer addAnimation:transitionAnimation forKey:#"fadeAnimation"];
Hopefully this will give you a gentle fade in colour change.

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];

CALayer and drawRect

I'm completely new to Core Animation, CALayer and all this stuff, so bear with me.
I have a custom NSTextField using as a Label. I would want the content to animate it's position, so the whole string get's visible if it's too long for the Labels width.
Now, the animation itself is working fine. I've implemented this with CABasicAnimation:
- (void)awakeFromNib {
CALayer *newLayer = [CALayer layer];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"position"];
[animation setFromValue:[NSValue valueWithPoint:NSMakePoint(0, 0)]];
[animation setToValue:[NSValue valueWithPoint:NSMakePoint(-self.attributedStringValue.size.width, 0)]];
[animation setDuration:5.0];
[animation setRepeatCount:HUGE_VAL];
[newLayer addAnimation:animation forKey:#"position"];
[self setLayer:newLayer];
[self setWantsLayer:YES];
}
The only problem is, that the drawRect: method only draws what's on the screen.
So I thought I would override the drawRect: method to draw the whole attributed string. But if I do this, nothing get's drawn at all...
Can anyone point me into the right direction?
Thank you!
In general, you want to avoid overriding drawRect if at all possible, especially for CALayer objects that you are animating. That tends to lead to really dreadful performance.
What do you mean "the drawRect: method only draws what's on the screen?"
It only draws the portion of the string that's currently visible?
I ended up using an NSTimer. Not the most beautiful solution, but at least it works.

UITableView appears partially clipped (blanked out) after receiving memory warning and "modal" view dismissed

I have a product details screen that slides up into view when a user selects one of the products displayed in a table/grid view of products. I use CATransition to slide the view up, rather than use presentModalViewController.
The reason for this is because in the details screen, I allow the user to swipe left/right to navigate through the table of products and display the corresponding details. Again, the slide animation is done using CATransition. When I used a modal view to present the initial details screen, the swiped-in product screen would appear rotated and generally behave oddly. I assumed it had something to do with using CATransition within a modal view, so I decided to use CATransition to present the initial screen. Here is the code that does the slide animation:
+(void)slideFromView:(UIView*)currentView toView:(UIView*)nextView direction(CCUISlideDirection)direction{
// get the the underlying UIWindow, or the view containing the current view
UIView *theWindow = [currentView superview];
// remove the current view and replace with the next view to display
[currentView removeFromSuperview];
[theWindow addSubview:nextView];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
switch (direction) {
case CCUISlideLeft:
[animation setSubtype:kCATransitionFromRight];
break;
case CCUISlideRight:
[animation setSubtype:kCATransitionFromLeft];
break;
case CCUISlideUp:
[animation setSubtype:kCATransitionFromTop];
break;
case CCUISlideDown:
[animation setSubtype:kCATransitionFromBottom];
break;
default:
break;
}
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#"SwitchToView1"];
}
Now all the swiped-in view transitions work fine, until I receive a memory warning. After I receive the warning, and then dismiss/slide the details screen offscreen, part of the table/grid view of products appears clipped. Specifically, about 1/3 of the right side of the table appears white. See screenshot link below:
http://www.dropbox.com/gallery/19636498/1/work?h=4ecde7
Also, here is the delegate code to dismiss the view:
-(IBAction)dismiss:(id)sender
{
MyWishesItemController* controller = (MyWishesItemController*)sender;
[CCUIHelper slideFromView:controller.currentView toView:self.view direction:CCUISlideDown];
if ([[_wishListResultsController fetchedObjects] count] > 0) {
[self showWishList];
}
else {
[self showEmptyList];
}
}
Also, when I select a different tabbed view in the application and return to the table view, it appears fine. The odd thing to me is that it is only a part of the table that is blanked out. I've tried reloading the table when I receive the warning, but that didn't work. I've also run it through Instruments to identify and fix some leaks.
Other than clearing some caches in the didReceiveMemoryWarning method, and otherwise minimizing memory usage to avoid the warnings, what should I be doing to fix this problem.
Any suggestions would be greatly appreciated.
Check the autosizing on your tableview. Make sure it is resizing correctly after the memory warning.

Animating the UIButton Layer?

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