前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Mac开发跬步积累(三):被忽略的 NSTabViewController

Mac开发跬步积累(三):被忽略的 NSTabViewController

作者头像
代码行者
发布2018-10-10 11:41:10
2.4K0
发布2018-10-10 11:41:10
举报
文章被收录于专栏:macOS 开发学习

图片来自网络

从名字上看,NSTabViewController 很容易让熟悉iOS开发的人联想到UITableviewController,但是它在行为上更像是iOS中另外一个常用的控制器UITabBarController

0x00: NSTabViewController 简介

NSTabViewControllermacOS 10.10 之后推出的一个UI层级的控制器,可以通过使用多个Tab标签来管理多个子业务控制器,实现业务分离.

Apple 官方描述

NSTabViewController作为一个容器业务控制器,可以管理多个页面,并且一次仅显示一个页面

  1. 我们先看一个简单的示例效果:

NSTabViewController的 四种 Style

  • NSTabViewController 有四种显示样式,可以通过tabStyle属性进行设置,它是一个枚举类型,具体效果如上图;
代码语言:javascript
复制
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
    }
}
  1. NSTabViewController提供了默认的切换子控制器的转场效果:Crossfade

子控制器的转场切换效果 Crossfade

NSTabViewController提供了一个枚举属性transitionOptions可以设置切换转场效果

代码语言:javascript
复制
 open var transitionOptions: NSViewController.TransitionOptions

关于NSViewController.TransitionOptions详细效果可以参看Mac开发跬步积累(二):NSViewController 转场动画精耕细作

0x01: NSTabViewController设置更多Style

NSTabViewControllertabStyle属性仅提供了4种样式,但实际开发中可能会需要下图中的两种情况(居左/居右)

切换栏居左/居右

我们使用tabViewtabViewType代替NSTabViewController的样式设置,即可实现更多的样式设置效果.

  1. 使用Storyboard设置:

storyboard 设置 tabView 的 type

  1. 使用代码设置:
代码语言:javascript
复制
import Cocoa
class TabViewController: NSTabViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        1. 先设置NSTableView的样式为unspecified 
        tabStyle = .unspecified  
        2. 设置tabView的type样式 居左
        tabView.tabViewType = .leftTabsBezelBorder
    }
}

从代码设置中可以看出一个事实: NSTabViewController的最终样式是由NSTabViewController的tabStyle属性与tabViewtabViewType属性值共同作用的效果;

我们可以使用下面这段代码来验证这个事实:

代码语言:javascript
复制
import Cocoa
class TabViewController: NSTabViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        1. 设置显示在顶部
        tabStyle = .segmentedControlOnTop      
        2. 设置显示在左边
        tabView.tabViewType = .leftTabsBezelBorder  
    }
}

实现效果如图(同时显示顶部和左边):

同时显示顶部和左边

0x03: NSTabViewController的应用场景

无论在macOS系统中或者在其他应用中,NSTabViewController都有广泛的使用场景

NSTabViewController的应用场景

每个macOS App 几乎都有一个功能: 偏好设置,如果偏好设置中的选项比较少,一个页面就足够展示,这种情况使用一个NSViewController就可以实现效果了,但通常来讲,我们希望自己的App能提供给用户更多的选项设置,以便于用户可以更多的进行个性化选择功能,这时候就属于NSTabViewController用武之地

0x04: 用NSTabViewController实现偏好设置功能(敲黑板~划重点)

我们先看一下系统Finder的偏好设置,然后我们通过NSTabViewController来模仿类似的效果来强化对NSTabViewController的学习.

  1. 系统Finder 偏好设置的切换效果:

系统Finder 偏好设置

  • 需求点: 在NSTabViewController切换业务控制器时,需要动态的调整所在window尺寸
  • 效果实现: 要在NSTabViewController切换选项时,动态的计算窗口size,并根据实际size设置window的尺寸,我们需要通过创建一个继承NSTabViewController的子类重写tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?)即可.
代码语言:javascript
复制
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)
    }
}

划重点

如果你实现的效果与预期的不同,那么一定是你在子业务控制器中少写了下面这行代码

代码语言:javascript
复制
   self.preferredContentSize = view.frame.size
  1. 最终实现效果:

实现效果

  1. Demo Github 地址: Day31- NSTabViewController

0x05: NSTabViewController 小结

  • NSTabViewController 支持的样式有4种;
  • 实现更多的样式,需要使用tabViewtabViewType枚举;
  • NSTabViewControllerviewNSView,它里面包含一个NSTabViewNSSegmentedControl(样式为segmentedTop/segmentedBottom时)
  • NSTabViewController的样式结果由NSTabViewControllertabStyle属性与tabViewtabViewType属性值共同作用的
  • 切换子业务控制器时,会触发方法tabView(_ tabView: NSTabView, didSelect tabViewItem: NSTabViewItem?)

0x06: One more thing .....

NSTabViewController的非ToolBar样式时如果需要实现特殊的选项卡效果,需要自定义NSSegmentedControl.

关于NSViewNSViewController的相关基础,有兴趣的同学可以参考macOS 开发基础视频教程中的项目代码(地址在文章中有链接)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.09.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x00: NSTabViewController 简介
  • 0x01: NSTabViewController设置更多Style
  • 0x03: NSTabViewController的应用场景
  • 0x04: 用NSTabViewController实现偏好设置功能(敲黑板~划重点)
  • 0x05: NSTabViewController 小结
  • 0x06: One more thing .....
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档