最后更新: 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 运行一下, 跑起来了。 状态栏出现了, 点击一下, 控制台出现打印信息。 Good!

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

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

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

  • 左边的状态栏

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

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

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

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

对了,别忘记删除 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(width: 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(width: 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()
} }

Pap.er 模仿 - 第一天的更多相关文章

  1. Pap.er 模仿 - 第二天

    最后更新:2017-12-19 在第一天中, 我们完成了项目的基本设置.隐藏Dock.显示和隐藏Popover等操作,接下来的这章中, Pap.er将会去搭建对应 UI. 一.设置Popover对应颜 ...

  2. power designer 绘制E-R 图

    总体概括:本篇主要先介绍E-R图的一些基本概念,然后介绍怎么绘制E-R图,特别是用power designer 的反向工程怎么把表中对字段的注释也展示出来. 1.E-R图的基本概念: E-R图就是en ...

  3. Tomcat6启用Gzip压缩功能

    配置Tomcat根目录下/conf/server.xml文件: <Connector port="8080" protocol="HTTP/1.1" co ...

  4. mongo数据库的常见操作

    连接mongodb数据库的命令查看对应数据库mongo.exeuse shujukuming;db.opportunity.findOne({"id":5}); db.opport ...

  5. 爬取5K分辨率超清唯美壁纸

    目录 爬取5K分辨率超清唯美壁纸 简介 编写思路 使用教程 演示图片 完整源代码 @ 爬取5K分辨率超清唯美壁纸 简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空 ...

  6. Mac 上有哪些比较有意思的小软件?

    文章素材来源:微博.新浪看点 收录于:风云社区(SCOEE)[提供mac软件下载] 更多专题,可关注小编[磨人的小妖精],查看我的文章,也可上[风云社区 SCOEE],查找和下载相关软件资源. (一) ...

  7. MetaMask/safe-event-emitter

    https://github.com/MetaMask/safe-event-emitter safe-event-emitter An EventEmitter that isolates the ...

  8. MSER最稳定极值区域源码分析

    最稳定极值区域介绍 如把灰度图看成高低起伏的地形图,其中灰度值看成海平面高度的话,MSER的作用就是在灰度图中找到符合条件的坑洼.条件为坑的最小高度,坑的大小,坑的倾斜程度,坑中如果已有小坑时大坑与小 ...

  9. 已知二叉树的中序序列为DBGEAFC,后序序列为DGEBFCA,给出相应的二叉树

    面对这种问题时我们该怎么解决? 今天写数据结构题.发现了一道总是碰见问题的题在这里我写了一种求解方法我自己称它为分层递归求解. 第一步通过观察我们知道后序遍历时最后一个是根节点A 在中序序列中A的左边 ...

随机推荐

  1. Canvas入门07- 自定义实现虚线的绘制

    预备知识 直线的斜率 一条直线与某平面直角坐标系x轴正半轴方向的夹角的正切值即该直线相对于该坐标系的斜率. 对于一条直线 y = kx +b,k就是直线的斜率. 斜率的计算 对于一条已知的线段,求斜率 ...

  2. Miller-Robin 素数测试法 模板

    测试单个素数,出错概率比计算机本身出错的概率还要低 算法是基于费马小定理(format),二次探测定理(x*x % p == 1 ,若P为素数,则x的解只能是x = 1或者x = p - 1)加上迭代 ...

  3. 【6.10校内test】T1 FBI树

    FBI树[题目链接] 感觉我超废. MY SOLUTION:     我的想法其实也是很简单的,递归的去做,因为最后要求输出FBI的后序遍历,也就是左右头,我的方法是递归存字符数组,(按照与后序遍历完 ...

  4. 遍历文件夹下的csv,把数据读进一张表

    import pandas as pd import os if __name__ == '__main__': Path = 'c:\checklog' dfs = [] for dir_path, ...

  5. 又一Tab切换效果(js实现)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  6. HTML-图片和多媒体

    1.图片和多媒体 (1)    图片:img元素 src 属性:图片路径: alt 属性:图片无法显示时使用的替代文字: title:鼠标悬停时显示的文字 : <img src="图片 ...

  7. Docker数据目录相关操作

    数据目录挂载 我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器.使用 -v 选项 docker run -id -v /宿主机绝 ...

  8. poj 1564 Sum It Up(dfs)

    Sum It Up Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7191   Accepted: 3745 Descrip ...

  9. rest_framework框架的认证、权限

    REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth", ] ...

  10. IDEA开发初始化设置

    一.基本设置 1. 自动生成 serialVersionUID 的设置 2. 设置文件注释 3. 隐藏项目文件(夹) .git;.gitignore;.idea;.idea/.;.mvn;mvnw;m ...