iOS学习笔记(1)-iPhone分辨率和坐标系

终于决定开始学习ios开发了,很久之前有过一次ios开发培训,但是做完作业就落下了,一直没有再捡起。想到如今ios开发如火如荼,再不学习真的要掉队了,希望能督促自己在2个月内完成ios开发的基础学习以及写出一个demo。这是第一篇,先总结下iphone的分辨率以及图像基础知识,由于对图形图像的一些概念并不太熟,错误在所难免,请大虾指正。

1 Points/DPI & Pixels/PPI

在谈到iPhone的分辨率之前,先要说说ios开发里面Points和Pixels的概念。在ios开发中,一个控件的坐标尺寸都是用逻辑点Points来表示,Points是抽象单元,仅仅只是在坐标空间起作用。我们实际看到的控件都是像素点Pixels。DPI(dot per inch)是每英寸(1英寸=2.54厘米)的逻辑点的个数,比如iPhone5的逻辑分辨率320x568,DPI为163。为PPI(pixel per inch)则是每英寸的像素点的个数,比如iPhone5的物理分辨率为640x1136,PPI为326,iPhone6 Plus的物理分辨率为1080 x 1092,PPI为401。个人理解的一点是,显示内容多少跟DPI相关,也就是我们在代码里面设定的大小,而显示的精细程度则跟PPI和素材本身的分辨率相关

Update: 另外要说明的一点是,我们有时候看到一张图片,大小为640X960,这个其实是水平和垂直方向的像素点数目,像素点多并不代表图片就越大,还有个因素很重要,就是分辨率。对于两张像素点一样的图片,比如都是640X960,其中一张图片分辨率为144PPI,另一张图片分辨率为72PPI,那么,分辨率为144的图片会比72的小。

如下图所示,ios应用中,首先代码中设定的Points首先会根据一定的scale factor缩放因子渲染为像素。比如iPhone4之前的缩放因子都是1,而iPhone4-iPhone6因为提高了分辨率,因此缩放因子增加为2,而iPhone6 Plus分辨率更高,缩放因子为3。对于同样大小的图片,在不同的分辨率显示会有差异,在高分辨率的机器上会变小,为了保证在所有型号机器上看起来图片大小一致,所以需要不同大小的图片,这也是ios开发中的图片资源会有1x,2x以及3x这三种的原因。图后附有xcode代码打印出的Points和Pixels的值,可以验证一下。

图1 - The Ultimate Guide To iPhone Resolutions
####测试代码
UIScreen *mainScreen = [UIScreen mainScreen];
NSLog(@"Screen bounds: %@, Screen resolution: %@, scale: %f, nativeScale: %f",
    NSStringFromCGRect(mainScreen.bounds),mainScreen.coordinateSpace,mainScreen.scale, 
          mainScreen.nativeScale);

####输出
iPhone4s:
Screen bounds: {{0, 0}, {320, 480}}, Screen resolution: <UIScreen: 0x7ba30360; bounds = {{0, 0}, {320, 480}}; mode = <UIScreenMode: 0x7ba30650; size = 640.000000 x 960.000000>>, scale: 2.000000, nativeScale: 2.000000

iPhone5:
Screen bounds: {{0, 0}, {320, 568}}, Screen resolution: <UIScreen: 0x7b932140; bounds = {{0, 0}, {320, 568}}; mode = <UIScreenMode: 0x7b9301b0; size = 640.000000 x 1136.000000>>, scale: 2.000000, nativeScale: 2.000000

iPhone6:
Screen bounds: {{0, 0}, {375, 667}}, Screen resolution: <UIScreen: 0x7fd340c0f6f0; bounds = {{0, 0}, {375, 667}}; mode = <UIScreenMode: 0x7fd340c0fba0; size = 750.000000 x 1334.000000>>, scale: 2.000000, nativeScale: 2.000000

iPhone6 Plus:
Screen bounds: {{0, 0}, {414, 736}}, Screen resolution: <UIScreen: 0x7f924b40b1d0; bounds = {{0, 0}, {414, 736}}; mode = <UIScreenMode: 0x7f924b40b6d0; size = 1242.000000 x 2208.000000>>, scale: 3.000000, nativeScale: 3.000000

除了iPhone6 Plus外,经过第一步的根据scale factor进行缩放后的像素就是最终显示的物理像素。由于iPhone6 Plus的屏幕分辨率为1080 x 1920, 而上一步缩放得到的分辨率为1242 × 2208,因此需要再经过一次向下取样(downsample)的过程,对于一张图片来说,大小变成了之前的87%(1080/1242=20/23)左右,之前缩放的23个像素要映射到屏幕的20个像素上。我们在开发的时候,3x的图片的分辨率要调成1242 x 2208,由ios去完成向下取样的过程。示例参见http://www.paintcodeapp.com/news/iphone-6-screens-demystified
,而向下取样带来的影响参见这篇文章的分析http://oleb.net/blog/2014/11/iphone-6-plus-screen/

2 再谈iPhone6 Plus的分辨率设置

第一个疑问是为什么iPhone6 Plus的逻辑分辨率要用414*736呢,如果用360 x 640貌似也OK,放大三倍后正好是1080 x 1920,都可以省去后面那个downsample的步骤了。参考资料2详细分析了iPhone6 Plus的逻辑分辨率这样设置的原因,摘录如下,先看图:

图2 - iPhone规格和分辨率
  • 如果逻辑分辨率用360 x 640,放大3x后确实正好跟屏幕分辨率一致,省去了doansample的步骤。但是这样带来的问题是6P的逻辑分辨率 360x640 比 iPhone 6的 375x667 还低,6P的大屏幕虽然很精细,但是可显示的实际内容比6还少,太不科学。打个比方就是:相同字号的情况下,6如果一行显示了25个字,而6P就会只能显示24个字了。
  • 如果逻辑分辨率为540 x 960,放大2x就可以跟屏幕分辨率一致,这样也就不用3x的图片了。但是这样带来的问题是6P的逻辑分辨率差不多是6的两倍,确实可以显示更多的内容了,但是UI控件可以显示的实际物理面积变小了,标签栏或导航栏按钮的物理高度只有原来的81.5%(163/200),点击面积只有原来的66.4%(81.5% x 81.5%),这样点击就更加困难了。
  • 因此最好的方案应该是图中的iPhone6 Plus(a)了,物理像素1242 x 2208,在5.5英寸的屏幕上这个ppi就要达到461了,而苹果最终并没有采用这个方案,而是缩放到了1080 x 1920。可能的原因是如果分辨率达到461ppi,则内存消耗增大,电池消耗增大,工艺上可能也有难度。当然如果后续技术提高后,克服了这些困难,则很可能不用downsample了。
  • 如果我们不用3x的图片,而是将2x的图片用在6P中,则会出现明显的锯齿或模糊。

3 ios开发中的坐标系

ios开发中坐标系至关重要,直接关系UI控件最终的位置关系。其中有三个属性要重点关注:bounds,center和frame,斯坦福大学的ios开发教程中有很精辟的注解,下面是这几个属性的定义:

@property CGRect bounds; // your view’s internal drawing space’s origin and size
// The bounds property is what you use inside your view’s own implementation.
// It is up to your implementation as to how to interpret the meaning of bounds.origin.

@property CGPoint center; // the center of your view in your superview’s coordinate space 

@property CGRect frame; // a rectangle in your superview’s coordinate space which entirely contains your view’s bounds.size

概括起来就是:

  • 坐标系从左上角开始。
  • 坐标系以Points为单元(注意,是逻辑点Points,不是像素Pixels)。最终ios会将UI控件自动适配高分辨率,只要有相应的2x和3x的素材提供。
  • bounds指的是视图自己的范围区域。
  • center指的是视图的中心点在superview的坐标系的坐标。
  • frame则是视图的superview坐标系中包裹了这个UIView的矩形区域。
  • frame和bounds可能是相同的,但是不一定都相同,如果UIView本身旋转了,则不会相同,具体见后面的图示例。

下面这个图详细说明了这几个属性的含义。

图3 - iOS坐标系

简单测试

测试代码如下,在当前UIView中加入一个UILabel,打印这个label的bounds,center以及frame,当然这里没有旋转该UIView。可以看到label的center为{45, 35},正好是label在superview坐标系中的坐标。而label的bounds是针对自身那个矩形的,所以为{{0,0},{50,30}}。label的frame则是包裹它的矩形在superview坐标系中的坐标,也就是{{20,20},{50, 30}}.

###测试代码###
  CGRect labelRect = CGRectMake(20, 20, 50, 30);
  UILabel *label = [[UILabel alloc] initWithFrame:labelRect];
  label.text = @"Hello!";
  [self.view addSubview:label]; 
  NSLog(@"center:%@, bounds:%@, frame:%@", NSStringFromCGPoint(self.view.center), NSStringFromCGRect(self.view.bounds),
          NSStringFromCGRect(self.view.frame));
  NSLog(@"center:%@, bounds:%@, frame:%@", NSStringFromCGPoint(label.center), NSStringFromCGRect(label.bounds),
          NSStringFromCGRect(label.frame));
          
###输出结果如下(模拟器为iPhone5s)###
2016-01-11 23:19:59.927 resolution[10719:2940751] center:{160, 284}, bounds:{{0, 0}, {320, 568}}, frame:{{0, 0}, {320, 568}}
2016-01-11 23:19:59.927 resolution[10719:2940751] center:{45, 35}, bounds:{{0, 0}, {50, 30}}, frame:{{20, 20}, {50, 30}}

4 参考资料

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容