Is it possible to animate the collapsing and expanding of NSSplitView subviews? (I am aware of the availability of alternative classes, but would prefer using NSSplitView over having animations.)
I am using the method - (void)setPosition:(CGFloat)position ofDividerAtIndex:(NSInteger)dividerIndex
to perform the collapsing and expanding.
There are a bunch of answers for this. In 2019, the best way to do this is to establish constraints on your SplitView panes, then animate the constraints.
Suppose I have a
SplitView
with three panes:leftPane
,middlePane
,rightPane
. I want to not just collapse the two panes on the side, I want to also want to dynamically resize the widths of various panes when certain views come in or go out.In IB, I set up a WIDTH constraint for each of the three panes.
leftPane
andrightPane
have widths set to250
with a priority of1000 (required)
.In code, it looks like this:
You can get more complex in this animation block. For example, you could decide that you want to collapse the right pane, but also enlarge the middle one to 500px at the same time.
The advantage to this approach over the others listed here is that it will automatically handle cases where the window's frame is not currently large enough to accommodate "expanding" a collapsed pane. Plus, you can use this to change the panes' sizes in ANY way, not just expanding and collapsing them. You can also have all those changes happen at once, in a smooth, combined animation.
Notes:
leftPane
,middlePane
, andrightPane
never change. Those are "containers" to which you add/remove other views as needed. If you remove the pane views from the SplitView, you'll destroy the constraints you set up in IB.-setPosition:ofDividerAtIndex:
approach does not work well when the splitView isn't big enough to set the divider where you want it to be. For example, if you want to UN-collapse a right-hand pane and give it500
width, but your entire window is currently just300
wide. This also gets messy if you need to resize multiple panes at once.min
andmax
width constraint as needed (perhaps when different views come into each pane, etc).CRITICAL NOTE:
This approach will fail if any subview in one of the panes has a
width
orminimumWidth
constraint that has a priority of1000
. You'll get a "can't satisfy constraints" notice in the log. You'll need to make sure your subviews (and their child views, all the way down the hierarchy) don't have a width constraint set at1000
priority. Use 999 or less for such constraints so that the splitView can always override them to collapse the view.Here's a simpler method:
http://www.cocoabuilder.com/archive/cocoa/304317-animating-nssplitpane-position.html
(Link above dead, new link here.)
Which says create a category on NSSplitView as follows, and then animate with
Works for me.
Category:
Solution for macOS 10.11.
Main points:
NSSplitViewItem.minimumThickness
depends ofNSSplitViewItem .viewController.view
width/height, if not set explicitly.NSSplitViewItem .viewController.view
width/height depends of explicitly added constraints.NSSplitViewItem
(i.e. arranged subview ofNSSplitView
) can be fully collapsed, if it can reachZero
dimension (width or height).So, we just need to deactivate appropriate constrains before animation and allow view to reach
Zero
dimension. After animation we just need to activate needed constraints.For some reason none of the methods of animating frames worked for my scrollview.
I ended up creating a custom animation to animate the divider position. This ended up taking less time than I expected. If anyone is interested, here is my solution:
Animation .h:
Animation .m
I'm using it like this - I have a 3 pane splitter view, and am moving the right pane in/out by a fixed amount (235).
After some more trying, I found the answer: yes, it's possible.
The code below shows how it can be done. The
splitView
is the NSSplitView which is vertically divided intomainView
(on the left) and theinspectorView
(on the right). TheinspectorView
is the one that collapses.