顯示具有 iOS retina 標籤的文章。 顯示所有文章
顯示具有 iOS retina 標籤的文章。 顯示所有文章

2012年11月29日 星期四

不再念舊,只保留@2x圖檔的國王新衣陷阱

iPhone就像美麗的model LUCY一樣,不只有內在,同時也有難以抗拒的外在。iPhone外觀的優點,就像LUCY美麗的點,十根手指也數不完。不過如果非要選出代表性的,想當然是高解析度的Retina螢幕當仁不讓地中選。

有了Retina螢幕,App可以呈現更高解析度,更高畫質的圖片。然而美麗是有代價的,一個不小心,可是會開天窗,變成國王的新衣,什麼都看不到! 接下來彼得潘將以LUCY的2張美麗照片為例,說明retina顯示暗藏的致命陷阱。

左邊的圖片為lucy.jpg,右邊為lucy@2x.jpg。聰明的iPhone在顯示圖片時,將根據檔名做判斷,加了@2x的圖片將現身於retina的高解析度螢幕,而少了@2x加持的圖片只有念舊仍然拿著低解析度iPhone的使用者看得到。




因此,當我們執行以下程式碼後,顯示結果如下:


self.imageView.image = [UIImage imageNamed:@"lucy.jpg"];



舊型iPhone (例如iPhone 3GS)



retina糖衣加持的新型iPhone (例如iPhone 5)




雖然念舊是個好習慣,不過有些時候人要向前看,像是為了促進經濟發展買iPhone 5,為了不讓新女友難過忘了舊情人。為了減少App的size,彼得潘決定將lucy.jpg狠心從App刪除,只保留lucy@2x.jpg。如果以剛剛的程式碼在舊型的iPhone再跑一次,結果如下:



iPhone真聰明,自動地將lucy@2x.jpg縮小,顯示於舊解析度的螢幕上。然而條條大路通羅馬,顯示圖片的方法也不只一種,如果採用以下方法,LUCY就像變魔術般,從螢幕上整個消失不見!


NSString *path = [[NSBundle mainBundle] pathForResource:@"lucy.jpg" ofType:nil];
NSLog(@"path %@", path);
self.imageView.image = [[UIImage alloc] initWithContentsOfFile:path];






說明:
線索其實很明顯。印出的Log訊息如下:

    path (null)

剛剛的程式碼,我們先取得圖檔的檔案路徑。然後再以UIImage的initWithContentsOfFile: method,傳入檔案路徑來設定顯示的圖片。但別忘了lucy.jpg早已不存在App裡,只留在彼得潘的記憶深處呀。 因為取得的檔案路徑path是空的,因此UIImageView完全不知道要顯示哪一張圖片,也就只能開天窗,一片空白了。



因此,如果堅持要使用 initWithContentsOfFile:來設定顯示的圖片,請記得要加下@2x,如此美麗的LUCY就可以再度出現在我們的眼前了。

NSString *path = [[NSBundle mainBundle] pathForResource:@"lucy@2x.jpg" ofType:nil];


2012年5月3日 星期四

忘了@2x的猶抱琵琶半遮面

iOS的retina提供了令人驚豔的超高解析度,讓iPhone從320*480變身為640*960, iPad從1024 * 768 變身為 2048 * 1536。然而,更令身為程式設計師的我們開心的,原來的程式碼我們一行也不用改,只要將高解析度的圖片檔名加上@2x,系統即能聰明地區分不同解析度的圖片。


比方以上這張百吻巴黎楊雅晴 kiss圖片,我們只要分別將低解析度的kiss.jpg和高解度的kiss@2x.jpg加入專案,當以[UIImage imageNamed:@"kiss.jpg"]建立image物件時,若iPhone本身具有retina螢幕,系統即會聰明地採用@2x結尾的圖片。


不過若是我們將高解度的圖片加入專案,但卻忘了於檔名裡加上@2x,將讓系統產生嚴重的誤解。


如上圖所示,圖片裡的帥哥美女都只露出了半張臉,仿佛古時候的猶抱琵琶半遮面。
造成圖片無法完整顯示其實真的不太容易,需要同時滿足以下三點:
1.將UIImageView物件的contentMode設為UIViewContentModeTop
2.高解析度的圖片檔名忘了補上@2x
3.具有retina能力的螢幕

這是因為當有加上@2x時,若圖片原來是200 * 200 (pixel),系統會將它除以2,設定圖片的大小為100*100 (point)。但若我們不幸忘了加上@2x,系統將不幸地把圖片的大小設為200 * 200 (point),而在retina螢幕上,200 * 200 (point) 等同於 400 * 400 (pixel),所以圖片被放大,幸福的kiss也就只露出了一半。

另外有一點值得注意的,如果利用initWithContentsOfFile建立UIImage物件,此時傳入的path可以為沒有@2x的圖檔路徑,當螢幕為retina時,系統同樣會聰明地找尋@2x的檔案 。但若只有@2x的檔案,但卻沒有低解析度的普通檔案,此時利用NSBundle的pathForResource取得的路徑將是空的,造成找不到檔案,無法建立UIImage物件。