天天看點

iOS學習筆記(1)-iPhone分辨率1 Points/DPI & Pixels/PPI2 再談iPhone6 Plus的分辨率設定3 ios開發中的坐标系4 參考資料

終于決定開始學習ios開發了,很久之前有過一次ios開發教育訓練,但是做完作業就落下了,一直沒有再撿起。想到如今ios開發如火如荼,再不學習真的要掉隊了,希望能督促自己在2個月内完成ios開發的基礎學習以及寫出一個demo。這是第一篇,先總結下iphone的分辨率以及圖像基礎知識,由于對圖形圖像的一些概念并不太熟,錯誤在所難免,請大蝦指正。

本文簡書位址http://www.jianshu.com/p/8b95632b61a5

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和素材本身的分辨率相關。

如下圖所示,ios應用中,首先代碼中設定的Points首先會根據一定的

scale factor

縮放因子渲染為像素。比如iPhone4之前的縮放因子都是1,而iPhone4-iPhone6因為提高了分辨率,是以縮放因子增加為2,而iPhone6 Plus分辨率更高,縮放因子為3。對于同樣大小的圖檔,在不同的分辨率顯示會有差異,在高分辨率的機器上會變小,為了保證在所有型号機器上看起來圖檔大小一緻,是以需要不同大小的圖檔,這也是ios開發中的圖檔資源會有1x,2x以及3x這三種的原因。圖後附有xcode代碼列印出的Points和Pixels的值,可以驗證一下。

iOS學習筆記(1)-iPhone分辨率1 Points/DPI & Pixels/PPI2 再談iPhone6 Plus的分辨率設定3 ios開發中的坐标系4 參考資料
####測試代碼
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: ; bounds = {{0, 0}, {320, 480}}; mode = <UIScreenMode: ; size =  x >>, scale: , nativeScale: 

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

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

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

除了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的邏輯分辨率這樣設定的原因,摘錄如下,先看圖:

iOS學習筆記(1)-iPhone分辨率1 Points/DPI &amp; Pixels/PPI2 再談iPhone6 Plus的分辨率設定3 ios開發中的坐标系4 參考資料
  • 如果邏輯分辨率用

    360 x 640

    ,放大3x後确實正好跟螢幕分辨率一緻,省去了doansample的步驟。但是這樣帶來的問題是6P的邏輯分辨率

    360x640

    比 iPhone 6的

    375x667

    還低,6P的大螢幕雖然很精細,但是可顯示的實際内容比6P還少,太不科學。打個比方就是:相同字号的情況下,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本身旋轉了,則不會相同,具體見後面的圖示例。

下面這個圖詳細說明了這幾個屬性的含義。

iOS學習筆記(1)-iPhone分辨率1 Points/DPI &amp; Pixels/PPI2 再談iPhone6 Plus的分辨率設定3 ios開發中的坐标系4 參考資料

簡單測試

測試代碼如下,在目前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(, , , );
  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)###
-- :: resolution[:] center:{, }, bounds:{{, }, {, }}, frame:{{, }, {, }}
-- :: resolution[:] center:{, }, bounds:{{, }, {, }}, frame:{{, }, {, }}
           

4 參考資料

  • http://www.paintcodeapp.com/news/ultimate-guide-to-iphone-resolutions
  • iPhone 6 Plus的邏輯分辨率為什麼是414x736?
  • iPhone螢幕尺寸、分辨率及适配
  • MIT iOS開發教程