NSSplitView – Split view: Arrange two or more views in a linear stack in a horizontal/vertical direction!

Split view Also manages the split screen and direction of the split view controller (NSSplitViewController). By default, the divider has a horizontal orientation so that the split view aligns its panes vertically from top to bottom — if the vertical attribute is NO(the default), the top divider has an index of 0. If vertical is set to YES, the index of the leading separator is 0. You must use an NSSplitView instance to place the NSSplitViewController’s (view property or splitView property) view:

NSSplitViewController let sigV = NSSplitView(frame: NSMakeRect(10, 10, 200, 200)) self.view .addSubview(sigV) sigV.wantsLayer = true sigV.layer? .backgroundColor = NSColor.purple.cgColor let splitVC = NSSplitViewController() splitVC.view.wantsLayer = true splitVC.view.layer? .backgroundcolor = nscolor.cyan.cgcolor self.addChild (splitVC) sigv.addSubView (splitvc.view)//✅ //sigV .addSubView (splitvc.splitView)//✅ let subVC1 = GYHViewController() subvc1.view.wantslayer = true subvc1.view.layer? .backgroundColor = NSColor.red.cgColor let subVC2 = GYHViewController() subVC2.view.wantsLayer = true subVC2.view.layer? .backgroundcolor = nscolor.blue. CgColor // Add subitems of split view let splitV_Item1 = NSSplitViewItem(viewController: subVC1) let splitV_Item2 = NSSplitViewItem(viewController: subVC2) splitVC .addSplitViewItem(splitV_Item1) splitVC .addSplitViewItem(splitV_Item2)Copy the code

Effect: Subviews can set their split screen size!



Adding subviews directly using NSSplitView (without screen ViewController (NSSplitViewController)) will (by default) fill up the NSSplitView instances in turn – size proportional to the subviews!

let totalV = NSSplitView(frame: NSMakeRect(20, 20, 100, 300)) self.view.addSubView (totalV) Will (default) fill NSSplitView instances in turn -- let leftV = NSView(frame: NSMakeRect(10, 10, 100, 100)) totalV .addSubview(leftV) leftV.wantsLayer = true leftV.layer? .backgroundColor = NSColor.red.cgColor let midV = NSView(frame: NSMakeRect(10, 10, 150, 150)) totalV .addSubview(midV) midV.wantsLayer = true midV.layer? .backgroundColor = NSColor.yellow.cgColor let rightV = NSView(frame: NSMakeRect(10, 10, 200, 200)) totalV .addSubview(rightV) rightV.wantsLayer = true rightV.layer? .backgroundcolor = nscolor.cyan.cgcolor // TotalV. arrangesAllSubviews = false// Whether to separate columns -- default is YES totalV.wantsLayer = true // Set the border and the border color totalV.layer? . BorderWidth = 3.0 totalV. Layer? .borderColor = NSColor.black.cgColorCopy the code

Effect:

UI

UI hierarchy

After setting NSSplitView’s (backgroundColor) color, the ‘splitter bar’ color (the splitter bar is still displayed) will be overwritten and hidden

totalV.layer? .backgroundColor = NSColor.blue.cgColorCopy the code

Effect:

UI

Set whether the splitter bar isVertical for NSSplitView – isVertical attribute (default: NO)

Totalv. isVertical = trueCopy the code

Effect:

UI

You can also add constraints to the NSSplitView — the subview will scale equally according to the constraints

TotalV. TranslatesAutoresizingMaskIntoConstraints = false / / add constraint let totalV_Lead = totalV. LeadingAnchor .constraint(equalTo: self.view.leadingAnchor, constant: 100.0) the let totalV_Trail = totalV. TrailingAnchor. The constraint (equalTo: self. View. TrailingAnchor, constant: Let totalV_Top = totalV.topAnchor. Constraint (equalTo: self.view.topAnchor, constant: 20.0) let totalV_Bot = totalv. bottomAnchor. Constraint (equalTo: self.view.bottomAnchor, constant: -20) let totalV_consArr = [totalV_Lead, totalV_Trail, totalV_Top, totalV_Bot] self.view .addConstraints(totalV_consArr)Copy the code

Effect: When the window is scaled – the subview is scaled equally according to the constraint! Of course, subviews can set their split screen size!

Running effect

UI

Sets the divider bar style: dividerStyle property

TotalV. DividerStyle = NSSplitView. DividerStyle. Thin / / the style of the splitter barCopy the code

Effect:

UI

When adding a fixed frame subview inside the NSSplitView subview :(without constraint layout)

Running effect

The frame of the view is fixed, and the layout is inflexible

Write the following function: adds a subview to a view that is contained within it

func addConstraintWithInnerView(_ outV: NSView) { let innerV = NSView(frame: NSMakeRect(10 + (100 + 10), 10, 100, 100)) Subsequent will add constraint outV. AddSubview (innerV) innerV. TranslatesAutoresizingMaskIntoConstraints = false / / add constraint inside the let - have been included in the parent view innerV_Lead = innerV.leadingAnchor .constraint(lessThanOrEqualTo: outV.leadingAnchor, constant: 10.0) the let innerV_Trail = innerV. TrailingAnchor. The constraint (equalTo: outV. TrailingAnchor, constant: -10.0) let innerV_Top = innerv. topAnchor. Constraint (lessThanOrEqualTo: outV.topAnchor, constant: 20.0) let innerV_Bot = innerv. bottomAnchor. Constraint (equalTo: outV.bottomAnchor, constant: = [innerV_Lead, innerV_Trail, innerV_Top, innerV_Bot] outV .addConstraints(innerV_consArr) innerV.wantsLayer = true innerV.layer? .backgroundColor = NSColor.purple.cgColor }Copy the code

Code use:

/ / add - by constraining the layout of the child views self. AddConstraintWithInnerView (leftV) self. AddConstraintWithInnerView (midV) self .addConstraintWithInnerView(rightV)Copy the code

Effect: When the window is scaled – the subview is scaled equally according to the constraint! Of course, the subview can set its split screen size, and after setting its split size — the subview will still scale at the same scale according to the constraint!

Running effect

Set the proxy — NSSplitViewDelegate for the NSSplitView instance

totalV.delegate = self; / / set the delegateCopy the code

Partial proxy method response:

//MARK:NSSplitViewDelegate func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool { print("shouldAdjustSizeOfSubview \(view.frame)") return false } func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { print("proposedMaximumPosition:", proposedMaximumPosition, "dividerIndex:", DividerIndex) if dividerIndex == 0 {// The largest size of the first view (NSView) return 150.0} return proposedMaximumPosition} func splitView(_)  splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { print("proposedMaximumPosition:", proposedMinimumPosition, "dividerIndex:", DividerIndex) if dividerIndex == 0 {// The smallest size of the first view (NSView) return 50.0} return proposedMinimumPosition} // Notification response method for size changes func splitViewDidResizeSubviews(_ notification: Notification) { //print("notification.object \(notification.object as Any)") let splitV = notification.object as! NSSplitView / / access (notification object) to the corresponding NSSplitView print (" splitViewDidResizeSubviews splitV \ (splitV) ")} func splitViewWillResizeSubviews(_ notification: Notification) { //print("notification.object \(notification.object as Any)") let splitV = notification.object as! NSSplitView / / access (notification object) to the corresponding NSSplitView print (" splitViewWillResizeSubviews splitV \ (splitV) ")}Copy the code

Effect:

For more proxy methods, take -nssplitViewDelegate






Add an NSTableView instance object with an unfixed size: see “Add an NSTableView view with an unfixed size” for the third method, using an NSSplitView instance

Resources: NSSplitView | NSSplitViewController | NSSplitViewDelegate NSSplitView and autolayout




goyohol’s essay