转自:http://guoxiaosi1990.diandian.com/post/2012-07-06/40029975069

版本支持了RETINA,作为国内首个支持RETINA高分屏的MAC OS X APP,我们希望能够和大家分享一些在RETINA支持方面的开发技术心得。欢迎MAC平台的开发朋友们与我们沟通交流。也希望可以通过IBLOG这个平台在今后和大家交流MAC OS X系统方面的技术经验。

基本概念和思想

和iOS的异同

在系统对高分屏的支持上,Mac OS和iOS基本上是一样的:都是两倍的Scale Factor,都是系统自动来完成这个Scaling。但Mac OS毕竟是电脑操作系统,与iOS相比,多了对以下几个方面的支持:

  1. window和screen的关系

  2. 多显示器

  3. 显示器分辨率的随时更改

两种运行模式:Framework-Scaled和Magnified

在高分屏的Mac中,App有两种运行模式: Framework-Scaled模式和Magnified模式。两种模式的差别,在于Backing Store层的大小。什么是Backing Store层?我们的App和显示器之间,其实有一层buffer层,这层就是Backing Store层。在Framework-Scaled模式下,Backing Store层的大小和显示器一样,而Magnified模式时是显示器的四分之一(长宽各为二分之一),相当于同尺寸普通屏的大小。

在Framework-Scaled模式下,因为Backing Store层的大小和显示器一样,所以我们的App可以更精细地做视觉处理。而与之相比,Magnified模式其实是一个纯粹为兼容而设计的模式。在Magnified模式下,因为Backing Store层的大小和普通屏一样,App还是以1x的形式运行,在显示时,即Backing Store层到显示器的转换时,系统再把其拉伸到2x。这样,在Magnified模式下的App会保持和普通屏一致的表现,当然,也会因拉伸而看上去有点模糊。

非Cocoa的App则只能以Magnified模式运行,而Cocoa App默认是以Framework-Scaled模式运行。 如果Cocoa App觉得自己在Framework-Scaled模式下运行有较大体验问题,也可以在程序中将自己设成默认以Magnified模式运行。 此外,用户也可以通过程序文件的“显示简介”窗口手动更改App的运行模式。

毫无疑问,要在高分屏上有细腻的视觉感受,我们的程序必须运行在Framework-Scaled模式下。

Point和Pixel

什么是Point?苹果给的定义是用户空间的一个单位。在普通屏上,Point和Pixel是一比一的关系,而在高分屏上,它们的关系是一比四。这点和iOS是一样的。

对开发者来说,大部分情况下,我们根本不需要去考虑Pixel,因为我们程序中用到的坐标基本上都是以Point为单位的。在编写代码时,我们可以这样假设:世界上根本就不存在高分屏的Mac,新的MacBook Pro其实还是原来的1440*900。这样,我们就会都是以Point的方式去考虑坐标,从而保持程序高分屏和普通屏表现的一致性。这也是苹果推荐的方式。

那我们什么时候才需要考虑到Pixel呢?当我们准备操纵像素的时候。主要有以下几个地方:

  • Core Graphics。也就是说,当我们用到CG开头的API时,我们需要注意,它们的坐标大部分是以Pixel为单位的。

  • OpenGL。既然是绘制,自然要精确到像素级。

DPI和PPI

DPI:Dots Per Inch,每英寸点数,一般用来表示打印机或显示设备的精度。而在图像中,则一般使用PPI。

PPI:Pixels Per Inch,每英寸像素数,一般用来表示图像的精细度。

高分屏的DPI是144,是普通屏的两倍。此外,用系统截图工具截取的图片,其PPI也是144,同样是普通屏时的两倍。

支持高分屏,我们需要做些什么?

确认我们App运行在Framework-Scaled模式下

Cocoa App默认是以Framework-Scaled模式运行,不用做任何额外的事情。对于非Cocoa的App,如果要支持高分屏,需要做些修改了。

增加两倍图资源

和iOS一样,要支持高分屏,对所有图片,我们都需要在其旁边增加一个名字为“一倍图名字+@2x”的两倍图资源。对原来用图数量就比较多的程序来说,如QQ,设计师的工作量毫无疑问是巨大的。不仅如此,因为Mac窗体大小不像iOS那么统一,为了防止问题发生,切图时还要注意以下事项:

  • 两倍图的图片资源,其分辨率最好是一倍图严格的两倍;PPI和一倍图保持一样,还是72。如果不这样做,不仅在高分屏上有可能出现不符合我们预想的表现,普通屏也是会受影响的。这是因为这些错误有可能会导致系统判断两倍图关系失败,从而使普通屏下直接读取两倍图,导致界面展示异常。

  • 如果程序中还涉及到图片的叠加,那么这些用来叠加的图片,内容上最好也是严格的两倍。举个例子,如果一倍图中有根线的位置是第三行,那么两倍图中这根线的位置应该是第五行和第六行。否则,会出现在普通屏下对齐的图片在高分屏下却没有对齐的情况。

确认代码中的资源图片读取方法

要想让系统帮我们自适应使用一倍图和两倍图,我们最好尽量使用文档推荐的资源图片读取方法:NSImage的imageNamed:方法和NSBundle的imageForResource:方法,分别对应main bundle和其他bundle中图片的读取。如果之前代码中有使用其他资源图片读取方法的地方,最好替换掉。

确认资源图片读取时不要带后缀名

和iOS一样,如果我们想让系统自适应来使用一倍图和两倍图,读取时传入的图片名字就不能带有后缀名,否则读取的是那张指定名字的一倍图。xib中也是一样的情况。所以,请搜索全程序确认这点。

确认之前涉及图片size的代码是否有问题

NSImage的size是以Point为单位的,所以无论一倍图还是两倍图,其size都是一样的。而前面讲过CG层又是以Pixel为单位的,所以请详细检查转换时的代码。

检查有图片拉伸的地方是否有异常

首先注意一点, 拉伸图片时,系统会自动使用两倍图。这是因为,NSImage读取图片时其实是两幅图同时读入的,使用时再根据目标区域的大小决定使用哪张图。如果目标区域的大小是介于一倍图和两倍图之间,那么系统会使用两倍图,然后将其缩到目标区域大小。所以要注意喽,如果之前程序中有目标区域比图片大,那么赶紧确认下是否还表现正常,因为这里会使用两倍图的。

当然,如果需要,我们可以不让系统不这么做。通过NSImage的类方法setMatchesOnlyOnBestFittingAxis: 设定后,一倍图和两倍图就严格根据普通屏和高分屏来使用了。不过需要注意,该方法是10.7.4才有的。

一般来说,最好使用NSDrawThreePartImage和NSDrawNinePartImage来拉伸图像。

增加Point与Pixel的转换代码

之前因为普通屏下Point与Pixel是一比一的关系,所以有些代码无意中会将这两种坐标弄混。所以,最好确认下这方面的代码,特别是和屏幕相关的地方。

需要Point与Pixel之间的坐标转换时,使用Backing Coordinate System。NSView、NSWindow和NSScreen都有与其坐标转换的方法,尽量不要直接使用Scale Factor进行计算。

增加分辨率变化时的响应代码

前面提过,与iOS相比,Mac是支持多显示器和随时切换分辨率。当一个窗体在两个不同显示模式的显示器里来回拖拽时,这个窗体的显示模式和分辨率同时也在发生着变化。不过别担心,一旦这些发生变化,系统会自动帮我们重绘窗体,一倍图和两倍图之类的也会自动帮我们切换。不过,我们最好还是确认下,在发生这些变化的情况下,我们的表现是否还是正常的。

如果需要在显示模式切换时做些处理时,我们可以监听NSWindowDidChangeBackingPropertiesNotification。如果是自定义NSView,可以重载viewDidChangeBackingProperties方法,在里面做处理。

注意高分屏时截取的图像其PPI是144

当我们通过系统截图工具或QQ在高分屏中进行截图时,就会发现截取后的图像,其PPI是144,是普通屏的两倍。这并不难理解,因为高分屏单位距离的像素数就是普通屏的两倍。所以程序中使用截图的地方,要注意这点。

替换API

1)BASE COORDINATE SYSTEM相关

之前我们会经常使用Base Coordinate System来表示在window中的坐标,而这个坐标系因为高分屏将被抛弃。所以,和这个坐标系相关的API,我们最好都要替换掉。

NSView:

convertPointToBase:替换成convertPoint:toView:(view为nil)

convertSizeToBase:替换成convertSize:toView:

convertRectToBase:替换成convertRect:toView:

convertPointFromBase: 替换成convertPoint:fromView:

convertSizeFromBase: 替换成convertSize:fromView:

convertRectFromBase: 替换成convertRect:fromView:

NSWindow:

convertBaseToScreen:替换成convertRectToScreen:

convertScreenToBase:替换成convertRectFromScreen:

2)图片绘制相关

NSImage的两个方法compositeToPoint:和dissolveToPoint:因为涉及到Base Coordinate System,所以被建议替换成drawAtPoint:fromRect:operation:fraction:。

此外,lockFocus方法也建议用imageWithSize:flipped:drawingHandler:替换。前面提到过,NSImage其实是同时拥有一倍图和两倍图的,会根据目标区域来使用哪一张,而lockFocus其实只处理了一张。

还有,建议使用NSGraphicsContext来处理图像,因为它会自动帮我们处理Scale Factor。

3)SCALE FACTOR相关

因为高分屏Scale Factor的介入,旧Scale Factor相关的需要修改:

a)NSScreen和NSWindow的userSpaceScaleFactor;

b)HIGetScaleFactor方法需用HIWindowGetBackingScaleFactor替换;

c)NSWindow的NSUnscaledWindowMask常量将被抛弃;

一些Trick

如何往NSTEXTVIEW中添加高清GIF图

为了支持高清表情,我们更改了在NSTextView中添加gif图的实现方法,采用了NSFileWrapper的方式,通过NSFileWrapper的setIcon:方法将NSImage设进去。但修改后运行我们发现表情都不会动了。怎么回事?我们跟踪了好一会,途中尝试了几种不同的方法,终于在做了以下处理后使表情运行正常:

  1. 将表情资源文件的.gif后缀改成.png;

  2. 高分屏和普通屏分开读取图片,普通屏只读取一倍图,高分屏则采用不使用后缀名的方式读取。

这种做法确实很让人费解,但这确实是我们经过多次尝试后找到的解决办法。之后我们还会继续研究这个问题,希望能找到更好的解决办法。

如何在制作DMG包时让其FINDER背景也支持RETINA

Apple没有在高分屏指南的文档中提到任何与dmg相关的内容,也没有为之增加任何新的方法来做这件事。但在其文档中有提到,使用tiffutil来制作复合型的tiff格式图片。在此格式的图片中,同时存储着普通与高清版本图像。事实上经过我们的测试,这种tiff格式图片是可以被用作dmg背景的。具体命令是:

tiffutil -cathidpicheck 普通图 高清图 -out 目标图片名称

需要注意的是:

  • DropDMG暂时不支持将tiff作为背景,可以通过修改后缀名为png的方式绕过此限制。

  • 用这种方法生成的dmg,在查看时会在左侧有一道奇怪的白边。可能是Apple的实现问题。

工具推荐

高分屏模拟工具

新的MacBook Pro刚出来,货源紧缺,实在不好买到。别担心,Xcode的Graphics Tools可以让我们模拟高分屏。Graphics Tools可以到developer.apple.com下载。 如何模拟高分屏:

  1. 将Graphics Tools中的Quartz Debug打开;

  2. 选择UI Resolution菜单;

  3. 在弹出来的窗口中选择“Enable HiDPI display modes”;

  4. 注销并重新登录;

  5. 在系统偏好设置的显示器面板中,选择后面带有HiDPI标志的分辨率。

这样,系统就会模拟高分屏的显示模式。略感不足的是,模拟后的分辨率只有原来的四分之一,操作各种不习惯。没办法,毕竟是一比四的关系啊。

两倍图检查工具

一下子换那么多图,哪些地方的两倍图显示正确,哪些地方还没换,我等肉眼凡胎,检查时难免纰漏。没关系,系统提供了自动标红的功能,帮助我们找出这些地方。

打开方式:在终端中,敲入以下命令

defaults write com.mycompany.myapp CGContextHighlight2xScaledImages YES

( com.mycompany.myapp就是我们需要检查的App名,如果是想检查所有的App,用-g替换 )

打开后,没有换成两倍图的地方,都会被红框标出来,非常方便。

UI实用工具

  • Layer Cake,直接从psd生成切图文件,甚至可以从普通psd直接生成高清版本的切图,在为旧软件增加高清支持时尤其方便。

  • IconKit,支持生成高清版本的icns文件。

  • PaintCode,矢量绘图并直接生成Objective-C代码,自然支持高清,大大减少UI和开发的工作。

  • 来源:iBlog

MAC 平台retina高分屏开发技术分享相关推荐

  1. Mac平台retina高分屏开发技术分享

    转自:http://iblog.tencent.com/mac-retina-guide/ QQ for Mac V2.1版本支持了Retina,作为国内首个支持Retina高分屏的Mac OS X ...

  2. [分享]错误“应用程序Xcode的这个版本不能与此版本的OS X配合使用”以及Mac源码和IOS开发资料分享

    [分享]错误"应用程序Xcode的这个版本不能与此版本的OS X配合使用"以及Mac源码和IOS开发资料分享 安装Xcode时,出现"应用程序Xcode的这个版本不能 ...

  3. 移动端地图开发技术分享交流会PPT

    该文章属于<简书 - 刘小壮>原创,转载请注明: <简书 - 刘小壮> http://www.jianshu.com/p/41179be5893a 本人现就职于国内某地图导航公 ...

  4. 阿里DataV 2016双十一媒体大屏回顾技术分享

    今年在多个部门共同努力下,阿里集团在2015水立方双十一媒体中心立起了一块宽21米,高10米的LED大屏.DataV 数据可视化小组有幸在这么大一块画布上尽兴创作,并且在这个项目中小组第一次尝试使用了 ...

  5. Workbench二次开发技术分享

    之前我发过的关于Workbech二次开发的技术ACT,ACT主要是用来对workbench进行一些横向的开发(诸如workbench现有的载荷类型已经满足不了你的需求,你可以利用ACT技术扩展载荷类型 ...

  6. Android SDK开发技术分享

    最近在工作中负责统一支付平台的SDK开发部分,就此总结下SDK开发的技术点.注意事项.与普通app开发的差别,作为自我总结,也作为公司内部互相学习的分享,希望有Android开发需求或者对Androi ...

  7. 【Android SDK 开发】Android SDK开发技术分享

    原文地址:https://blog.csdn.net/zhangxinjin/article/details/51602577 最近在工作中负责统一支付平台的SDK开发部分,就此总结下SDK开发的技术 ...

  8. 互联网券商线上开户系统设计与开发技术分享

    一.系统背景 国内开户需求 目前目前数据全球化.交易工具全球化.资讯全球化.资产全球化配置已然成为一种势不可挡 的趋势.据港交易所<现货市场交易研究调查 2018>的反应结果,香港以外投资 ...

  9. 粮草先行——Android折叠屏开发技术点番外篇之运行时变更处理原则

    上一篇文章中,我们有提到Activity在屏幕尺寸发生变更时的处理方式,总共有两种: 重启APP以适应屏幕改变: 手动处理数据,避免APP重启. 同样,这两种方式也同时适用于改变屏幕方向.更改系统语言 ...

最新文章

  1. 电脑能连蓝牙耳机吗_安卓手机延迟最低的蓝牙耳机有吗?超低延迟蓝牙耳机推荐...
  2. 从闭包函数的变量自增的角度 - 解析js垃圾回收机制
  3. 曙光服务器优势,5大核心优势 探秘曙光Cloudview三大平台
  4. Flutter嵌套深?扩展函数了解一下
  5. DataTemplate——数据模板的一个典型例子
  6. SublimeText3 初探(工欲善其事,必先利其器)
  7. CodeVS 3027 线段覆盖2(DP)
  8. Nmap 源代码学习四 软件简单使用
  9. 离职一个月了,也面了很多公司,但都没有offer,软件测试工作怎么就这么难找?
  10. socket 编程入门教程(五)UDP原理:4、“有连接”的UDP
  11. 台式计算机文件打不开怎么回事,电脑文件打不开怎么回事
  12. DEL: Restore Boxes after VirtualBox Upgrade
  13. 中国城市竞争力历年数据(2005-2009年)
  14. Kubernetes学习-K8S安装篇-Kubeadm安装高可用K8S集群
  15. C++ Reference: Standard C++ Library reference: C Library: cmath: cbrt
  16. 免费赠书,元旦快乐!
  17. 用VBA代码下载网络上的文件
  18. Org-mode + GitHub 搭建自己的云笔记
  19. vs编写java_vs code编写java
  20. 寇祖伟:释永信让我更加佛心向前!

热门文章

  1. 高并发的epoll+线程池,线程池专注实现业务
  2. nginx限制了你的想象?那么请用openresty
  3. java 常用算法_Java常见算法整理
  4. 嵌入式培训班有必要吗?
  5. Python进阶语法笔记(1)
  6. STM32Cube生态系统
  7. rmd中将html转为pdf,RMD转换为PDF
  8. 使用printf函数输出
  9. portainer 安装
  10. PAT 1136 stoi产生的错误