首页 > 其他分享 >在Cocoa里玩转Dock图标

在Cocoa里玩转Dock图标

时间:2024-07-03 17:43:42浏览次数:15  
标签:自定义 self label Cocoa Dock Badge 图标

原文来自;https://cocoa.venj.me/blog/play-with-dock-icon/

今天我们来看一看如何在Cocoa程序中自定义Dock图标。Dock图标的自定义主要包括四方面:

  • 加徽章(Badge)
  • 换图标
  • 隐藏和显示最小化时的图标徽章
  • 增加自定义Dock菜单

本文将对如何进行这四方面的自定义进行简单的介绍,并且在最后研究一下腾讯QQ for Mac独特的Badge机制。本文的示例代码使用了Acorn和腾讯QQ的图标做例子,请这两家厂商不要介意。

1 Dock徽章

给Dock图标加Badge的方法很常见,也很简单,用代码来说事吧。

void AppShimController::SetBadgeLabel(const std::string& badge_label) {
NSApp.dockTile.badgeLabel = base::SysUTF8ToNSString(badge_label);
}

加Badge是用NSDockTile类的-setBadgeLabel:方法;移除Badge是把badgeLabel的内容设置为nil。这个方法在10.5以上都可以使用,除非需要兼容10.4以下的OSX--现在似乎已经没有很大的必要了,或者是有其他特别的理由,否则真的很难拒绝使用Cocoa的这个简单的API调用。 ;)

2 更换Dock图标

有很多程序能够动态的修改程序图标,如,Adium和iCal。我们通过代码,我们可以在程序运行的时候动态设置Dock图标。修改图标有两种方法,一种是直接指定一个NSImage对象设置应用程序的图标;另一种是用一个自定义的View,来显示为Dock图标。

// Customize Dock Icon
- (IBAction)changeDockIcon:(id)sender {
    [NSApp setApplicationIconImage:[NSImage imageNamed:@"Icon"]];
}

// Restore Dock Icon
- (IBAction)restoreDockIcon:(id)sender {
    [NSApp setApplicationIconImage:nil];
}

// Draw Dock Icon with Custom View
- (IBAction)changeDockIconWithCustomView:(id)sender {
    DockIconView *dockView = [[[DockIconView alloc] init] autorelease];
    [[NSApp dockTile] setContentView: dockView];
    [[NSApp dockTile] display];
}

 

用自定义View做图标不能自动刷新,所以如果Dock图标有所改变--如加Badge时,可能需要手动通过-display方法刷新。

上面介绍的两种方法修改的程序图标会在程序退出之后还原为在Info.plist里指定的应用程序图标。要永久的改变程序图标(也就是退出程序的时候也能显示修改后的图标)的方法是创建Dock图标的插件。因为这个话题涉及Bundle相关的内容,在这里就不详述了,详情可以参考苹果的文档,以后有机会我会专门写文章介绍Dock图标插件的话题。

3 隐藏和显示最小化时的图标徽章

OSX的窗口在最小化的时候,在缩略图的右下角会显示一个程序图标徽章。我们可以通过程序来显示和隐藏最小化图标的徽章。方法很简单如下:

1
2
3
4
5
6
7
8
9
// Show minimize icon badge
- (IBAction)showMinimizeBadge:(id)sender {
    [[self.window dockTile] setShowsApplicationBadge:YES];
}

// Remove minimize icon badge
- (IBAction)removeMinimizeBadge:(id)sender {
    [[self.window dockTile] setShowsApplicationBadge:NO];
}

4 Dock菜单

Dock菜单有两种方法指定--一种是直接在XIB中静态的设计菜单,然后通过Interface Builder关联到NSAppdockMenu属性;另一种是通过ApplicationDelegate-applicationDockMenu:方法,在程序中动态指定菜单。静态Dock菜单的指定方法如下:

所有操作通过Interface Builder就能完成。

动态指定Dock菜单的方法如下面的代码所示:

1
2
3
- (NSMenu *)applicationDockMenu:(NSApplication *)sender {
    return self.dynamicMenu;
}

为了简便起见,我实际上并没有通过代码动态的创建菜单,上面的示例代码仅仅是引用了一个XIB里的菜单对象,通过-applicationDockMenu:方法返回。

5 QQ风格的Dock徽章

你可能已经注意到了这个QQ图标的Badge和最上方的那个QQ图标的Badge有些不一样。没错,最上方的那个Badge是Lion的默认的风格的图标,是我做的一个示例,图标借用了腾讯QQ的图标。不过实际的QQ的Badge并不是使用OSX的系统Badge。具体腾讯怎么做的我也不是很清楚,不过我用自定义View用腾讯的空白Badge图标做了一个模仿的例子:

我做的这个模仿示例,字体有些不太像,Badge文字的定位也有点不准确,不过我猜想腾讯的思路基本是和我类似,现在给出我写的实现。再次强调一下,这并非腾讯官方的方法,示例代码仅供参考:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
- (void)drawRect:(NSRect)dirtyRect
{
    // Drawing code here.

    // Draw Dock Icon
    NSImage *image = [NSImage imageNamed:@"qqbadge"];
    NSImageView *imageView = [[NSImageView alloc] initWithFrame:self.frame];
    imageView.image = image;
    [self addSubview:imageView];
    [imageView release];

    // Draw Badge Label
    NSRect labelFrame;
    CGFloat width = self.frame.size.width;
    CGFloat height = self.frame.size.height;
    labelFrame.origin = CGPointMake(width * 0.62, height * 0.60);
    labelFrame.size = CGSizeMake(width * 0.25, height * 0.25);
    self.label = [[NSTextField alloc] initWithFrame:labelFrame];
    self.label.backgroundColor = [NSColor clearColor];
    self.label.textColor = [NSColor whiteColor];
    self.label.drawsBackground = NO;
    self.label.stringValue = self.labelText;
    //在使用的时候,需要修改徽章Label,只需设置这个view对象的labelText属性即可
    NSFont *font = [NSFont fontWithName:@"Arial" size:32];
    [self.label setFont:font];
    [self.label sizeToFit];
    [self.label setBordered:NO];
    [self addSubview:self.label];
    [self.label release];
}

方法大致是,通过自定义View,绘制一个带空白Badge的图标,然后绘制一个图标徽章Label到Badge的位置,控制其大小,使其正好位于Label内部。

不过这种方法绘制的Badge有一个缺陷,那就是Badge的Label的长度不能太长,超过2个数字就不适合用这样的方法了。相比起来,用系统自带的Badge在Label很长的时候会自动拉长,更加灵活,而且只需一行代码,简单很多。可能腾讯这么做的目的最初是为了兼容Mac OS X 10.4才用了自定义View来绘制Badge;不过时代在进步,既然Cocoa已经提供了一个很简单的绘制Badge的API,腾讯是不是也应该更新一下了,况且,QQ for Mac现在的版本已经不再兼容10.6以下的系统了。

最后,本文的所有代码都已经包含在了一个示例项目Play With Dock中了,上图是运行的例子,代码已经推送到Github上了,有兴趣的可以看看,并且批评指正。

标签:自定义,self,label,Cocoa,Dock,Badge,图标
From: https://www.cnblogs.com/Galesaur-wcy/p/18282260

相关文章

  • windows的桌面docker安装mysql5.7
    dockerrun-p3306:3306--namemysql^-vE:/mysql/data:/var/lib/mysql^-vE:/mysql/conf:/etc/mysql/conf.d^-vE:/mysql/log:/var/log/mysql^-eMYSQL_ROOT_PASSWORD=123456^-dmysql:5.7命令解析:dockerrun-p3306:3306--namemysql:创建一个docker容......
  • Docker容器运行多个命令,有一个报错就重启容器
    核心是entrypoint.sh脚本中的内容。Dockerfile案例FROMpython:3.9.16WORKDIR/codeADDrequirements.txt/code/requirements.txtRUNpipinstall-ihttps://pypi.tuna.tsinghua.edu.cn/simple/-r/code/requirements.txtRUNspacydownloaden_core_web_trfADD......
  • Windows 安装docker详细步骤说明
    文章目录1.检查系统要求2.启用硬件虚拟化3.启用Hyper-V和容器功能4.下载并安装DockerDesktop5.配置DockerDesktop6.安装WSL27.验证Docker安装8.常见问题排查9.重点说明参考资源在Windows上安装Docker的详细步骤如下:1.检查系统要求确保您的Windows......
  • Docker网络
    docker网络的5种模式none在使用none模式后,Docker容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用none网络特点使用参数--networknone指定默认无网络功能,无法和外部通信无法实现端口映射适用于测......
  • dockerfile构建镜像
    dockerfile构建镜像镜像是多层存储,每一层在前一层的基础上进行修改;容器也是多层存储,以镜像为基础层,在其基础上加一层作为容器运行时的存储层。要求1.docker会逐行读取dockerfile中每一行的指令,按顺序解析,实现images的自动构建2.通过dockerbuild命令构建镜像3.dockerfile......
  • 使用国内源安装新版docker(2024.7.3)
    前言最近dockerhub已经不能访问了,使用原先的方式安装docker,服务器上也总是连接不上,所以找了种可以在国内正常安装新版docker的方式适用系统:centos71.先删除本机旧的或者残留的dockersudoyumremovedocker\docker-client\docker-client......
  • 容器自动化:docker-compose
    ansible一键部署docker-compus+lnmp+lnmt项目一、docker-compose我们知道使用一个dockerfile模板文件可以定义一个单独的应用容器,如果需要定义多个容器就需要服务编排,服务编排有多种技术方案。1.1、docker-compose简介docker-compose项目是docker官方的开源项目,负责实现......
  • ros2 jazzy docker环境安装
    dockerhub限制国内访问了,需要配置下,参考:https://github.com/cmliu/CF-Workers-docker.io/issues/8sudomkdir-p/etc/dockersudotee/etc/docker/daemon.json<<EOF{"registry-mirrors":["https://hub.uuuadc.top","https......
  • linux安装docker
    以下命令均以root权限执行卸载docker旧版本yumremovedockerdocker-clientdocker-client-latestdocker-commondocker-latestdocker-latest-logrotatedocker-logrotatedocker-selinuxdocker-engine-selinuxdocker-engine安装相关工具类yuminstall-yyum-utilsdev......
  • debian 12 基于清华源安装docker
    清华源docker地址:https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/debian/安装docker之前需要添加GPG公钥,主要是用来验证安装文件是否被篡改,先安装工具:curl和gnupg2,两个工具。aptinstallcurlgnupg2下面是清华源GPG地址,下载和添加。curl-fsSLhttps://mirrors.t......