Re: animating an NSStackView
Re: animating an NSStackView
- Subject: Re: animating an NSStackView
- From: Roland King <email@hidden>
- Date: Wed, 21 Jan 2015 15:56:00 +0800
> On 21 Jan 2015, at 14:38, Ken Thomases <email@hidden> wrote:
>
> On Jan 20, 2015, at 7:28 AM, Roland King <email@hidden <mailto:email@hidden>> wrote:
>
>> I'm trying to see if I can make insertions/deletions in an NSStackView a little more animated. So I did the simplest thing I could think of, wrapped the insert/delete in an NSAnimationContext, made the control layer-backed, turned on implicit animations and called layoutSubviewsIfNeeded. Something like this
>>
>> stackView.wantsLayer = YES;
>> ...
>> [ NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){
>> context.duration = somethingVeryLong;
>> context.allowsImplicitAnimation = YES;
>>
>> [ stackView insertView:aNewView atIndex:aNewIndex ];
>> [ stackView layoutSubviewsIfNeeded ]; // doesn't appear to be needed, also tried [ stackView.window layoutIfNeeded ]
>> }
>> completionHandler:NULL ];
>
> Have you tried simply sending the -insertView:atIndex: message to the stack view's animator proxy, instead? (I have no particular reason to expect that it works better, just asking.)
>
> Regards,
> Ken
I hadn't, but I have now and indeed it didn't work, but it was a nice idea.
However your mail prompted me to give the whole thing another go and I achieved a better result. The important pieces seem to be
1) Everything right up to the window's view needs to be layer backed. If it's not, then you each insertion causes the rows to jump up (or down) before they animate. This is rather like the jumpy behavior shown in the Best Practices For Cocoa Animation WWDC 2013 talk and I assume it's core animation fighting with normal main thread CAAnimations.
2) You need [ stackview.window layoutIfNeeded ] and not [ stackView layoutSubtreeIfNeeded ]. Using the latter you get the jump then animate back.
3) Possibly the most important, you add the new view into the stack view *before* the animation block and only call layoutSubviews inside the animation block.
So the code now looks like this
[ stackView insertView:aNewView atIndex:aNewIndex ]; // add before the animation block
[ NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
context.duration = somethingNotQuiteAsLong;
context.allowsImplicitAnimation = YES;
[ stackView.window layoutIfNeeded ]; // just do layout and do it on the window.
}
completionHandler:NULL ];
And that does a half-decent animation. There's a little more in there, I hide the new view before it goes in and then unhide it in the completion handler so it appears in the newly-opened gap but that's not really relevant to the issue I was having so I left that out here.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden