老谭笔记

Yosemite自定义window的titleView

在OSX系统中对Windows的自定义向来都是一个很麻烦的事情,从事MAC开发的同学应该都深有体会.
在过去,如果我们需要在标题栏中添加自定义的控件,可能通过下面的方式:

1
2
NSView *themeView = [[window contentView] superview];
[themeView addSubview:customView positioned:NSWindowBelow relativeTo:nil];

不过这样的做法在使用Yosemite的SDK编译时会产生这样的警告:

titleView_error

虽然这个警告并不会造成显示的异常.
我特意测试了一下Apple的兼容性设计,我发现使用10.9的SDK编译就不会产生这样的警告,通过打印window的tree结构发现一个奇怪的现象:不同的SDK编译的程序中的window的组成结构是一样的?后来发现在Info.plist中的DTSDKBuild项与编译的SDK相对应,在运行时会作为环境变量决定系统采取什么样的兼容策略.

回到正题,那如何在Yosemite中添加自定义的元素titleView呢,根据警告内容,NSThemeFrame不能添加未知的View,通过打印NSThemeFrame的子视图可以发现它包含两个视图,一个就是window的contentView,另一个是NSTitleBarContainerView,这个视图是关闭,最小化,缩放等按钮的容量,经试验放在它上面是可行的.

1
2
3
4
NSView *themeView = [[window contentView] superview];
NSArray *subViews = [themeView subviews];
NSView *containerView = [subViews objectAtIndex:1];
[containerView addSubview:customView positioned:NSWindowBelow relativeTo:nil];

代码跑起来发现添加上去的控件处于半透明的状态,通过查询window的文档,发现有一个titlebarAppearsTransparent的属性,将它置为YES,问题解决.

1
window.titlebarAppearsTransparent = YES;

另外附上一个可以统一设置标题和窗口背影色的window,能兼容不同的系统版本:
CustomWindow.zip