从名字上看,
NSTabViewController
很容易让熟悉iOS开发的人联想到UITableviewController
,但是它在行为上更像是iOS中另外一个常用的控制器UITabBarController
0x00: NSTabViewController 简介
NSTabViewController
是macOS 10.10
之后推出的一个UI层级
的控制器,可以通过使用多个Tab标签
来管理多个子业务控制器
,实现业务分离.
NSTabViewController
作为一个容器业务控制器,可以管理多个页面
,并且一次仅显示一个页面
-
我们先看一个简单的示例效果:
-
NSTabViewController
有四种显示样式,可以通过tabStyle
属性进行设置,它是一个枚举类型,具体效果如上图;
extension NSTabViewController {
@available(OSX 10.10, *)
public enum TabStyle : Int {
/// Uses an NSSegmentedControl to show the UI for the tabs. The control is on the top of the view.
case segmentedControlOnTop
/// Uses an NSSegmentedControl to show the UI for the tabs. The control is on the bottom of the view.
case segmentedControlOnBottom
/// Automatically pushes the tabs into the window's toolbar as toolbar items, if non-nil. This style will cause the TabViewController to set its containing window's toolbar to its own and become that toolbar's delegate. The toolbar items can be customized or supplemented by overriding the relevant NSToolbarDelegate methods.
case toolbar
/// NSTabViewController will not provide any of its own tab control UI. Separate UI, such as a NSSegmentedControl or NSPopupButton, can be easily bound to the TabViewController. Or \c tabView.tabViewType can be changed for the TabView itself to draw the UI.
case unspecified
}
}
-
NSTabViewController
提供了默认的切换子控制器的转场效果:Crossfade
NSTabViewController
提供了一个枚举属性transitionOptions
可以设置切换转场效果
open var transitionOptions: NSViewController.TransitionOptions
关于NSViewController.TransitionOptions
详细效果可以参看Mac开发跬步积累(二):NSViewController 转场动画精耕细作
0x01: NSTabViewController设置更多Style
NSTabViewController
的tabStyle
属性仅提供了4种样式
,但实际开发中可能会需要下图中的两种情况(居左/居右)
我们使用tabView
的tabViewType
代替NSTabViewController
的样式设置,即可实现更多的样式设置效果.
-
使用Storyboard设置:
使用代码设置:
import Cocoa
class TabViewController: NSTabViewController {
override func viewDidLoad() {
super.viewDidLoad()
1. 先设置NSTableView的样式为unspecified
tabStyle = .unspecified
2. 设置tabView的type样式 居左
tabView.tabViewType = .leftTabsBezelBorder
}
}
从代码设置中可以看出一个事实: NSTabViewController
的最终样式是由NSTabViewControlle
r的tabStyle
属性与tabView
的tabViewType
属性值共同作用的效果;
我们可以使用下面这段代码来验证这个事实:
import Cocoa
class TabViewController: NSTabViewController {
override func viewDidLoad() {
super.viewDidLoad()
1. 设置显示在顶部
tabStyle = .segmentedControlOnTop
2. 设置显示在左边
tabView.tabViewType = .leftTabsBezelBorder
}
}
实现效果如图(同时显示顶部和左边):
0x03: NSTabViewController的应用场景
无论在macOS
系统中或者在其他应用中,NSTabViewController
都有广泛的使用场景
每个macOS App
几乎都有一个功能: 偏好设置
,如果偏好设置
中的选项比较少,一个页面就足够展示,这种情况使用一个NSViewController
就可以实现效果了,但通常来讲,我们希望自己的App
能提供给用户更多的选项设置
,以便于用户可以更多的进行个性化选择
功能,这时候就属于NSTabViewController
的用武之地
了
0x04: 用NSTabViewController实现偏好设置功能(敲黑板~划重点)
我们先看一下
系统Finder
的偏好设置,然后我们通过NSTabViewController
来模仿类似的效果来强化对NSTabViewController
的学习.
- 系统Finder 偏好设置的切换效果:
- 需求点: 在
NSTabViewController
切换业务控制器时,需要动态的调整所在window
尺寸
- 效果实现:
要在NSTabViewController
切换选项时,动态的计算窗口size
,并根据实际size
设置window
的尺寸,我们需要通过创建一个继承NSTabViewController
的子类重写tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?)
即可.
import Cocoa
class TabViewController: NSTabViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?) {
super.tabView(tabView, didSelect: tabViewItem)
guard let itemView = tabViewItem?.view,
let window = view.window
else {return}
let oldFrame = window.frame
let newViewSize = itemView.fittingSize
var newFrame = window.frameRect(forContentRect: NSMakeRect(oldFrame.origin.x, oldFrame.origin.y, newViewSize.width, newViewSize.height))
let newY = oldFrame.origin.y - ( newFrame.size.height - oldFrame.size.height)
newFrame.origin = NSMakePoint(oldFrame.origin.x, newY)
NSAnimationContext.runAnimationGroup({ (context) in
window.animator().setFrame(newFrame, display: window.isVisible)
}, completionHandler: nil)
}
}
划重点
如果你实现的效果与预期的不同,那么一定是你在子业务控制器中少写了下面这行代码
self.preferredContentSize = view.frame.size
-
最终实现效果:
Demo Github 地址: Day31- NSTabViewController
0x05: NSTabViewController 小结
-
NSTabViewController
支持的样式有4种; - 实现更多的样式,需要使用
tabView
的tabViewType
枚举; -
NSTabViewController
的view
是NSView
,它里面包含一个NSTabView
和NSSegmentedControl
(样式为segmentedTop/segmentedBottom
时) -
NSTabViewController
的样式结果由NSTabViewController
的tabStyle
属性与tabView
的tabViewType
属性值共同作用的 - 切换子业务控制器时,会触发方法
tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?)
0x06: One more thing .....
在NSTabViewController
的非ToolBar
样式时如果需要实现特殊的选项卡效果,需要自定义NSSegmentedControl
.
关于NSView
与NSViewController
的相关基础,有兴趣的同学可以参考macOS 开发基础视频教程中的项目代码(地址在文章中有链接
)