Re: Animating view transitions with Core Animation (problems with BasicCocoaAnimations sample)
Re: Animating view transitions with Core Animation (problems with BasicCocoaAnimations sample)
- Subject: Re: Animating view transitions with Core Animation (problems with BasicCocoaAnimations sample)
- From: Troy Stephens <email@hidden>
- Date: Thu, 16 Oct 2008 14:10:08 -0700
Hi Jim,
On Oct 13, 2008, at 3:51 PM, Jim Correia wrote:
I have some old NSAnimation based code that I'd like to update to
use Core Animation.
Since BasicCocoaAnimations [1] does essentially what I want to do
(at least for starters) I am using that as a starting point.
[1] http://developer.apple.com/samplecode/BasicCocoaAnimations/index.html
Problem #1:
- Animation for -replaceSubview:with: appears to require a layer
backed view tree.
- Certain controls are not supported with layer backed view trees.
- Others work poorly:
- Focus rings are drawn incorrectly for editable NSTextField and
friends [2]
- Non-editable NSTextFields have incorrect anti-aliasing (without
Scott Stevenson's hack)
- NSTokenField has other issues (will be more specific and file a
radar later)
[2] http://skitch.com/jim.correia/2115/
Is there a direct workaround for any of these problems?
See Ken's reply regarding the text antialiasing. Subpixel ("LCD" /
"font smoothing") antialiasing is on by default when views are asked
to draw into their backing layers, but produces poor results if there
isn't an opaque background behind the text drawn in that same layer
(view). The options are to either switch off font smoothing (giving
you regular, whole-pixel antialiasing) or give each TextField an
opaque background color (and don't forget to also set drawsBackground
to YES).
The focus ring issue is known and we hope to find a better solution to
it. The present focus ring model that allows for drawing outside a
view's bounds is at odds with the sizing of view backing layers, which
doesn't allow extra margin for focus rings. The result, for now, is
thin focus rings when in layer-backed mode.
Please do file a Radar for whatever you're seeing in NSTokenField.
The workaround I attempted was to make the view tree in the window
layer backed only during the animation. This leads to problems #2
and #3.
Problem #2:
If I set view.wantsLayer=YES on the content view of the window
before doing the transitions, they are still not animated. If I
force that subview tree to re-display before sending -
replaceSubview:with: to the animator proxy, the transition is
animated.
While this works, forcing a view tree to display is usually the
wrong way to go about things. Is it expected that I need to force
display a view tree after view.wantsLayer=YES if I expect to start
implicit animations on that run loop cycle?
The -display is necessary in this case, since without it there won't
be an opportunity for the views to be drawn into their backing layers
in a transaction that precedes whatever animation you're then going to
apply to those backing layers.
If you want to be more efficient about it, a -
displayIfNeededIgnoringOpacity sent to the root view of the layer-
backed subtree (the view for which you're setting wantsLayer=YES)
should suffice, and will avoid redisplaying other views higher up in
the hierarchy.
Problem #3:
In order to arrange for my view tree to only be layer backed for the
duration of the animation, I need to know when the animation
finishes :-)
The benefit of the implicit view animations is that much of the
heavy lifting has already been done for me, so I'd like to take
advantage of it if possible. The problem, though, is that since I'm
not running the animations explicitly, I don't know when they are
done.
My current hack is to begin the implicit animations in a group, and
use a perform delayed action to cleanup after the animation (based
on the groups interval.)
This feels like a hack though. Is there a better way?
Using a perform-after-delay, an NSTimer, or equivalent is actually the
recommended technique. Execution of CAAnimations always obeys wall-
clock time, so you can be assured of completion after the duration has
elapsed, regardless of system load.
Alternatively, if you're providing your own CAAnimation instance to
drive a particular animation (for layer-backed views, this would be
done using an entry in a view's "animations" dictionary, or by
overriding +defaultAnimationForKey: or -animationForKey:), you can set
a delegate for the animation. The delegate will then receive an -
animationDidStop:finished: message when the animation terminates, if
the delegate implements such a method.
Most of the time, the NSTimer approach is the simpler, more convenient
way to go.
Troy
_______________________________________________
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