Animated Split View
Animated Split View
- Subject: Animated Split View
- From: Antonio Nunes <email@hidden>
- Date: Wed, 01 Jun 2011 11:07:40 +0100
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@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