2

I am working on a Mac app. I am trying to do a simple animation which makes an NSButton move down. The animation works really nicely, but when i do it, the background colour of my NSButton disappears for some reason. Here is my code:

// Tell the view to create a backing layer.
additionButton.wantsLayer = YES;

// Set the layer redraw policy. This would be better done in
// the initialization method of a NSView subclass instead of here.
additionButton.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
    context.duration = 1.0f;
    additionButton.animator.frame = CGRectOffset(additionButton.frame, 0.0, -20.0);
    //additionButton.frame = CGRectOffset(additionButton.frame, 0.0, -20.0);
} completionHandler:nil];

Button move down animation:

enter image description here

Button after move down animation:

enter image description here

Update 1

Just to make it clear, I am not using a background image in my buttons. I am using a background NSColor which I set in the viewDidLoad method like so:

[[additionButton cell] setBackgroundColor:[NSColor colorWithRed:(100/255.0) green:(43/255.0) blue:(22/255.0) alpha:1.0]];
Supertecnoboff
  • 6,406
  • 11
  • 57
  • 98
  • the images are not shown – Vivek Aditya Apr 01 '15 at 05:58
  • @ysaditya But I am not using images for the background of my NSButton. I have filled it in with a simple NSColor. – Supertecnoboff Apr 01 '15 at 05:59
  • Which `type` of button are you using (eg. Momentary Push In, etc.) – l'L'l Apr 01 '15 at 06:09
  • I am using a NSButton set as a Bevel. @l'L'l – Supertecnoboff Apr 01 '15 at 06:12
  • @l'L'l Yes I have it set to Momentary Push In as well. – Supertecnoboff Apr 01 '15 at 06:16
  • Where are you setting the button attributes, and I can't really tell by your screenshots, but is the button losing all of the color, or is it just darker? – l'L'l Apr 01 '15 at 06:33
  • 1
    @l'L'l So yes, sorry my screenshots are rubbish. But basically when I set the background cell colour in the viewDidLoad it works just fine. When I run the animation, the button moves down nicely, but the red background colour disappears completely. There is no more background colour for some reason once the animation starts. – Supertecnoboff Apr 01 '15 at 06:37
  • @Supertecnoboff, you can set background color for Button's layer. I think that will solve your issue. – Sheen Vempeny Apr 01 '15 at 06:57
  • Try unchecking `Visual > Bordered`. That may be why the color is dropping out; Bordered buttons can't have a fill unless you override it and draw it yourself. – l'L'l Apr 01 '15 at 06:57
  • @l'L'l I have the same problem too as super and I found that even after unchecking ```Visual > Bordered```, it doesn't work. –  Apr 01 '15 at 12:13
  • @SheenVempeny I have the same problem as super and I tried what you said ```buttonName.layer.backgroundColor = [NSColor... etc...]``` - but it doesn't work. Do you know why the color does not get set with that? –  Apr 01 '15 at 12:14
  • @Supertecnoboff, I think u didn't enable layer for the button.Please check this link http://stackoverflow.com/questions/29387102/how-to-set-background-color-of-nsbutton-osx/29387885#29387885 . – Sheen Vempeny Apr 01 '15 at 13:13
  • 1
    @Supertecnoboff, You should be setting the attributes in `[super drawRect]` – l'L'l Apr 01 '15 at 18:06

1 Answers1

1

I presume this is an AppKit bug. There are a couple of ways you can work around it.


Workaround 1:

Don't use layers. The button you're animating seems to be small, and you might be able to get away with using a non layer-backed animation and still have it look decent. The button will redraw during each step of the animation, but it will animate correctly. That means this is really all you have to do:

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {          
    additionButton.animator.frame = CGRectOffset(additionButton.frame, 0, -20);
} completionHandler:nil];

Workaround 2:

Set the background color on the layer.

additionButton.wantsLayer = YES;
additionButton.layer.backgroundColor = NSColor.redColor.CGColor;
additionButton.layerContentsRedrawPolicy = NSViewLayerContentsRedrawOnSetNeedsDisplay;

[NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {          
    additionButton.animator.frame = CGRectOffset(additionButton.frame, 0, -20);
} completionHandler:nil];

Workaround 3:

Subclass NSButtonCell, and implement -drawBezelWithFrame:inView:, drawing your background color there. Keep in mind that the parent view containing the button should be layer-backed, otherwise the button will still redraw on every step.

sudo rm -rf
  • 29,408
  • 19
  • 102
  • 161
  • Thank you so much!!!!! I decided to go with workaround 2 because after reading your awesome website, you said that layer back animations are much smoother. Thanks again and thanks for taking them time to view my question which I sent your on Twitter. This answer has been ticked and upvoted :D – Supertecnoboff Apr 02 '15 at 05:42
  • 3
    Good deal. Make sure that the button has a layer-backed parent or the animation won't be smooth like you'd expect. – sudo rm -rf Apr 02 '15 at 07:56