Hi,
I want a generic animated split view. So I had a rummage online, and couldn't
find anyone who had prepared the wheel for me. Consequently I set out to create
my own. I soon found that overriding setPosition:ofDividerAtIndex: and make it
work correctly for split views with more than two views was not as simple as I
expected it to be. Then I had a Bright Idea™ in realising that Apple have
already done all the heavy lifting for me, and that I could use that to my
advantage:
I created a category on NSSplitView which adds exactly two methods:
@interface NSSplitView (NSSplitView_Animation)
- (CGFloat)catPositionOfDividerAtIndex:(NSInteger)index;
- (void)catAnimateDividerAtIndex:(NSInteger)index
toPosition:(CGFloat)newPosition;
@end
@implementation NSSplitView (NSSplitView_Animation)
- (CGFloat)catPositionOfDividerAtIndex:(NSInteger)index
{
NSRect frame = [[self.subviews objectAtIndex:index] frame];
return self.isVertical ? NSMaxX(frame) : NSMaxY(frame);
}
- (void)catAnimateDividerAtIndex:(NSInteger)index
toPosition:(CGFloat)newPosition
{
CGFloat currentPosition = [self catPositionOfDividerAtIndex:index];
NSUInteger numberOfSubviews = self.subviews.count;
NSRect newRect[numberOfSubviews];
[self setPosition:newPosition ofDividerAtIndex:index];
for (NSUInteger i = 0; i < numberOfSubviews; i++) {
newRect[i] = [[self.subviews objectAtIndex:i] frame];
}
[self setPosition:currentPosition ofDividerAtIndex:index];
[NSAnimationContext beginGrouping]; {
[[NSAnimationContext currentContext] setDuration:0.2];
for (NSUInteger i = 0; i < numberOfSubviews; i++) {
[[[self.subviews objectAtIndex:i] animator]
setFrame:newRect[i]];
}
} [NSAnimationContext endGrouping];
}
@end
So, what am I doing:
1. Get the current divider position.
2. Set the new divider position.
3. Get the frames of all the splitview's subviews, which are now adjusted to
their new values.
4. Reset the divider position to the original, to restore the original frame
values of the subviews.
5. Animate the frames of all subviews to their new values.
Why I am doing all this:
I initially thought I would only need to change the values of the frames for
the two views on either side of the affected divider. But it turns out that,
when doing that, other views also magically resize. I don't know why. It is
possible I made a mistake somewhere, but, having taken a thorough look at my
own code, I don't think so. That's when the idea occurred to leverage what
Apple have already provided, rather then possibly spending hours wrestling to
get it right, maybe only to find later that there are subtleties that I had
overlooked. As far as I know, changing the divider position initially without
animation, and changing it back without animation, to obtain correct new values
for all subview frames before performing the actual animation, should have no
side effects, and be fairly efficient, making this a cheap and code-economic
technique.
I'm posting this for two reasons:
1. I want to ask if anyone thinks the technique used above has caveats or if
anyone thinks the technique is inefficient and can think of a more efficient or
better way to implement animation for NSSplitView.
2. It appears to work quite nicely for splitviews in either orientation, with
any number of subviews, including sub-splitviews. If there is no solid reason
to avoid this technique, it may be useful to others who are trying to do
similar things with NSSplitView.
Any comments appreciated.
Oh, one last thing: anyone in favour of subclassing, rather than being
categorical?
Cheers,
António
-----------------------------------------------------------
And could you keep your heart in wonder
at the daily miracles of your life,
your pain would not seem less wondrous
than your joy.
--Kahlil Gibran
-----------------------------------------------------------
_______________________________________________
Cocoa-dev mailing list ([email protected])
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:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]