• Pap.er 模仿


    最后更新: 2017-12-15

    一、 项目初始化

    1. 解析对应的资源, 下载Pap.er之后,需要解析里面的资源.
      采用如下的方法: http://blog.csdn.net/xuzihai0703/article/details/50327531

    2. 创建项目工程
      项目结构

    3. 导入里面的资源icon, 然后运行
      可以看到,资源文件夹里面有一个AppIcon.icns 文件夹, 里面包含搜有的icon资源.可以在 这里 进行解析、下载, 添加到项目Assets.xcassets - AppIcon中, cmd + R运行;
      运行结果
      运行之后,什么都没有,当然是这样的,毕竟我们什么都没做

    4. 在状态栏显示App, 进行如下操作

      • 把资源文件夹内的两张 icon16*16的文件,放到 Assets里面去

      关于StatusBar icon尺寸可以参考这篇文章

      • applicationDidFinishLaunching 的上面通过 NSStatusBar 实例化一个 NSStatusItem 对象, 通过设置此对象, 我们可以进行一系列的操作,例如icon、title、action等.

    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {

        @IBOutlet weak var window: NSWindow!
        
        let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
    
        func applicationDidFinishLaunching(_ aNotification: Notification) {
            // Insert code here to initialize your application
            let icon = NSImage(named: NSImage.Name(rawValue: "icon16*16"))
            icon?.isTemplate = true
            statusItem.image = icon
            statusItem.button?.target = self
            statusItem.button?.action = #selector(onStatusItemDidClicked(_:))
        }
    
        @objc private func onStatusItemDidClicked(_ item: NSStatusItem) {
            print("onStatusItemDidClicked")
        }
    

    }
    ```

    • cmd + R 运行一下, 跑起来了。 状态栏出现了statusBarIcon, 点击一下, 控制台出现打印信息。 Good!

      动手一下: 删除 icon?.isTemplate = true 会是什么效果?

    二、处理 Dock栏以 及 状态栏左

    当我们点击cmd + R 运行时候, 会出现如下情况:

    • 左边的状态栏 StatusLeft

    • Dock栏 Dock 以及显示一个系统默认给加载的窗口.

    找到 MainMenu.xib, 然后删除 Main Menu 以及 Window, 然后运行。

    删除Menu以及window

    运行好之后,你会发现,状态栏左在没有那多选项了,但是还是存在一个 . Dock 栏以后存在, 值得称赞的是,系统默认加载的 Window 消失了

    这是你需要在系统设置文件 info.plist 设置 Application is agent (UIElement) = YES 即可, 如下图

    Application is agent (UIElement)

    对了,别忘记删除 applicationDidFinishLaunching 上面的 @IBOutlet weak var window: NSWindow!, 因为window 以及被我们干没了。

    三、NSPopover 使用

    观察官方的 Pap.er, 点击 状态栏icon, 会出现如下界面:

    .

    macOS开发中,系统为我们提供了 NSPopover 来实现此效果。

    3.1 NSPopover 属性介绍

    查看NSPopover文档, 简单介绍其属性。

    属性 说明
    @IBOutlet weak open var delegate: NSPopoverDelegate? 代理
    open var appearance: NSAppearance? popover的外观, 默认 NSAppearanceNameVibrantLight
    open var behavior: NSPopover.Behavior Popover 的行为:
    applicationDefined 表示NSPopover的关闭需要App自己负责控制;
    transient: 表示只要点击到NSPopover显示的窗口之外就自动关闭;
    semitransient: 表示 只要点击到NSPopover显示的窗口之外就自动关闭,但是点击到当前App 窗口之外不会关闭。
    open var animates: Bool 是否动画
    @IBOutlet open var contentViewController: NSViewController? popover 内容展示的控制器, 在show之前一定要设置
    open var contentSize: NSSize popover 显示的大小
    方法
    open func show(relativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge) 显示
    @IBAction open func performClose(_ sender: Any?) 关闭popover 但是有可能会关不掉
    open func close() 强制关闭

    3.2 JUST DO IT

    简单介绍之后,我们开始动手吧。
    Step1:applicationDidFinishLaunching 上面添加一个 NSPopover 的实例;

    let popover = NSPopover()
    

    Step2:applicationDidFinishLaunching 里面添加如下设置:

    popover.behavior = .transient
    popover.animates = true
    popover.contentSize = CGSize( 285, height: 600)
    

    Step3:statusItem.button的响应方法中添加对应的响应

    if !self.popover.isShown {
        self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: .minY)
    }
    

    仅仅这几步还是不行的, 我们忘记了最重要的设置 contentViewController.点击 File->New->File->MacOS->Cocoa Class, 新建一个 MainPopoverViewController, 我们采用xib 来布局视图,当然 这不是必须的;

    Last Step: 在 Step2 设置 popover 的地方,添加一句

    popover.contentViewController =  MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)
    

    设置完之后, cmd + R 运行, 点击Status Item。显示如下,Great!

    3.3 细节优化

    1. Popover 展示出来之后, 用户如果点击非App 区域, 那么需要Popover 消失, 有如下两种方式:
    • 获取用户点击的区域, 然后判断用户点击是否在Popover的 contentViewController上-- 此种方式比较复杂
    • 根据 NSApplicationDelegateapplicationWillResignActive 通知处理,简单,有效。
      func applicationWillResignActive(_ notification: Notification) {
          self.popover.close()
      }
      
    1. MainPopoverViewController 从nib中加载出来,但是外界其实不要知道其实例化方式, 给 MainPopoverViewController 提供一个类方法实例化即可。
    extension MainPopoverViewController {
        static func make() -> MainPopoverViewController {
            let vc = MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)
            return vc
        }
    }
    

    四、代码

    AppDelegate.swift

    @NSApplicationMain
    class AppDelegate: NSObject, NSApplicationDelegate {
        
        let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
        
        let popover = NSPopover()
        
        func applicationDidFinishLaunching(_ aNotification: Notification) {
            // Insert code here to initialize your application
            let icon = NSImage(named: NSImage.Name(rawValue: "icon16*16"))
            icon?.isTemplate = true
            statusItem.image = icon
            statusItem.button?.target = self
            statusItem.button?.action = #selector(onStatusItemDidClicked(_:))
            
            popover.contentViewController =  MainPopoverViewController.make()
            popover.behavior = .transient
            popover.animates = true
            popover.contentSize = CGSize( 285, height: 600)
            
        }
        
        @objc private func onStatusItemDidClicked(_ statusBarButton: NSStatusBarButton) {
            print("onStatusItemDidClicked")
            if !self.popover.isShown {
                self.popover.show(relativeTo: statusBarButton.bounds, of: statusBarButton, preferredEdge: .minY)
            }
        }
        
        func applicationWillResignActive(_ notification: Notification) {
            self.popover.close()
        }
    }
    

    MainPopoverViewController.swift

    extension MainPopoverViewController {
        static func make() -> MainPopoverViewController {
            let vc = MainPopoverViewController(nibName: NSNib.Name(rawValue: "MainPopoverViewController"), bundle: nil)
            return vc
        }
    }
    
    class MainPopoverViewController: NSViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
    }
    
    
  • 相关阅读:
    sqlserver 服务器主体 无法在当前安全上下文下访问数据库
    【转】ASP.NET"正在中止线程"错误原因
    【转载】好的用户界面-界面设计的一些技巧
    新浪博客“网络繁忙请稍后再试”
    Mac上好用的视频播放器有哪些?
    Mac上好用的视频播放器有哪些?
    游戏平台代表--PS4【推荐】
    游戏平台代表--PS4【推荐】
    ospf剩余笔记
    ospf剩余笔记
  • 原文地址:https://www.cnblogs.com/gaox97329498/p/12070365.html
Copyright © 2020-2023  润新知