//分栏视图
分栏视图( Split View)是一种用户可拖动改变大小的区域分隔视图控件,有左右和上下两种风格,其对应的类是NSSplit View。中间可拖动的分隔线有3种不同宽度的样式可以选择。每个独立的区域还可以继续分隔,实现嵌套组合的复杂视图。
SplitView类的重要属性和方法说明如下。
1>vertical I属性:控制NSSplit View的中间分隔区的方向,水平或垂直。
2>setPostion方法:控制分隔区在NSSplitView中的位置, position.为x方向或y方向的左
边偏移。
3>dividerIndex:表示第几个分格区,如果只有两个分隔区域的话,此参数为0
4>dividerThickness方法:分隔区的大小、宽度或高度(根据vertical类型)。
sItion
方法用来设置分隔区位置
func setPosition( position: CGFloat, ofDividerAt dividerIndex: Int)
用代码创建分栏视图
用代码创建分栏视图的基本步骤如下。
(1)设置中间分隔线的方向和样式。
(2)创建左右两个空视图,添加到分栏视图。
(3)将分栏视图添加到主视图区。
具体代码如下:
funccreateSplistView() {
letframeSplitView = CGRect(x: 200, y: 20, 200, height: 200)
letsplitView = NSSplitView(frame: frameSplitView)
//垂直方向
splitView.isVertical = true
//中间分割线的样式
splitView.dividerStyle = .thin //NSSplitView.DividerStyle.thin
//左边视图
letviewLeft = NSView()
viewLeft.wantsLayer = true
viewLeft.layer?.backgroundColor = NSColor.green.cgColor
//右边视图
letviewRight = NSView()
viewRight.wantsLayer = true
viewRight.layer?.backgroundColor = NSColor.magenta.cgColor
//增加左右两个视图
splitView.addSubview(viewLeft)
splitView.addSubview(viewRight)
}
自定义分栏视图样式风格
除了使用分栏视图的dividerStyle来设置不同显示外观以外,还可以使用自定义的子类来控
制分隔区divider视图的颜色,甚至直接绘制divider的样式外观。
(1)只修改divider的颜色。dividerColor是只读属性,通过NSSplit View子类重置divider Color
的颜色即可。
(2)重绘外观。通过分栏视图子类实现draw Divider方法即可。下面的代码重绘了divider,,
做了一个圆角矩形的图形,使用黄色填充,蓝色作为边框的颜色,效果如图432右边所示。
classSplistView: NSSplitView {
/****
只修改 divider的颜色。 dividerColor是只读属性,通过 NSSplit View子类重置 divider Color
的颜色即可
**/
overridevardividerColor: NSColor{
returnNSColor.red
}
/****
重绘外观。通过分栏视图子类实现 drawDivider方法即可
下面的代码重绘了 divider,做了一个圆角矩形的图形,使用黄色填充,蓝色作为边框的颜色
**/
overridefuncdrawDivider(in rect: NSRect) {
letrectDivider = rect.insetBy(dx: 1, dy: 1)
letpath = NSBezierPath(roundedRect: rectDivider, xRadius: 3, yRadius: 3)
NSColor.blue.setStroke()
path.stroke()
NSColor.yellow.setFill()
path.fill()
}
}
分栏视图中的子视图控制
分栏视图的子视图行为通过 NSSplit View Delegate协议接口来实现控制。
(1)视图Size变化通知如下。
func splitviewwillResizeSubviews( notification: Notification
func splitviewDidResizeSubviews( notification: Notification)
(2)是否允许拉伸子视图。子视图默认是允许拉伸的,如果需要禁止某个子视图拉伸,则通过下面接口对相关的 subview返回 false禁止。
func splitview( splitview: NSSplitview, canCollapseSubview subview: NSView)->Bool
(3)调整各个子视图。当分栏视图大小发生变化时调用下面协议接口。可以在这个接口中调整各个子视图的大小,调整的原则是要满足子视图fame之和再加上分隔线 divider的fram等于分栏视图的 frame。
funcsplitView(_splitView: NSSplitView, resizeSubviewsWithOldSize oldSize: NSSize)
默认情况下调用分栏视图的 adjustSubviews来调整各个子视图的大小
(4)关闭子视图时是否允许隐藏分隔线divider,当通过拉伸某个子视图将其隐藏时,是否同时隐藏分隔线 divider
funcsplitView(_splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool
(5)可拉伸的视图区间范围规定了通过分隔线 divider可以拉伸的视图区域范围。对于左边的垂直方向的分栏视图来说,分别可以通过下面两个协议方法约定向左边和向右边拉伸的范围,如Max和Min代表的距离。默认的Min为0,Max为分栏视图的宽度
当向左拖动分隔线时, divider与分栏视图左边距离小于Min时,左边子视图隐藏关闭,即divider自动移动到最左边;当向右拖动分隔线时, divider与分栏视图右边距离大于Max时,右边子视图隐藏关闭,即 divider自动移动到最右边。
下面为实现NSSplitViewDelegate的方法
//实现NSSplitViewDelegate协议方法实现分栏视图控制的例子
extensionViewController: NSSplitViewDelegate {
//只允许左边视图拉伸移动
funcsplitView(_splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool {
ifsubview == splitView.subviews[0] {
returntrue
}
returnfalse
}
//向左移动拉伸距离最小为30
funcsplitView(_splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
return30
}
//向右移动拉伸最大值为100
funcsplitView(_splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat {
return100
}
//允许调整子视图
funcsplitView(_splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool {
returntrue
}
//调整子视图大小
funcsplitView(_splitView: NSSplitView, resizeSubviewsWithOldSize oldSize: NSSize) {
}
//允许拉伸移动子视图最小化后隐藏分割线
funcsplitView(_splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool {
returntrue
}
//视图Size变化的通知
funcsplitViewDidResizeSubviews(_notification: Notification) {
}
funcsplitViewWillResizeSubviews(_notification: Notification) {
}
}
分栏子视图的隐藏和显示
//leftViewWidth变量用来记忆关闭前分割线divider的位置
varleftViewWidth: CGFloat = 0
letsplitView: NSSplitView = {
letframeSplitView = CGRect(x: 200, y: 20, 200, height: 200)
letsplitView = NSSplitView(frame: frameSplitView)
//垂直方向
splitView.isVertical = true
//中间分割线的样式
splitView.dividerStyle = .thin //NSSplitView.DividerStyle.thin
//左边视图
letviewLeft = NSView()
viewLeft.wantsLayer = true
viewLeft.layer?.backgroundColor = NSColor.green.cgColor
//右边视图
letviewRight = NSView()
viewRight.wantsLayer = true
viewRight.layer?.backgroundColor = NSColor.magenta.cgColor
//增加左右两个视图
splitView.addSubview(viewLeft)
splitView.addSubview(viewRight)
returnsplitView
}()
//添加一个按钮,此方法作为按钮的点击事件
@objcfunctogglepanel(_sender: NSButton) {
letsplitViewItem = splitView.arrangedSubviews
//获取左边自视图
letleftView = splitViewItem[0]
//判断左边子视图是否已经隐藏
ifsplitView.isSubviewCollapsed(leftView) {
splitView.setPosition(leftViewWidth, ofDividerAt: 0)
leftView.isHidden = false
} else{
leftViewWidth = leftView.frame.size.width
splitView.setPosition(0, ofDividerAt: 0)
leftView.isHidden = true
}
splitView.adjustSubviews()
}