想象你正在干活踪宠,你的上級要求你在工程中加入一些圖片步势。你找到團隊中的設計師(如果你們有一個的話),鼓起勇氣背犯,問他要這些圖片坏瘩。不過,通常他都會忙得根本沒時間幫你漠魏。因為他要做的活兒比你還多倔矾。說實話,你到底見過一個設計師有多少活兒要做嗎柱锹?哪自!簡直多到令人發(fā)指啊禁熏!所以你最不想做的就是成為那個再給他加活兒的人了壤巷。特別是那些活兒對設計師來說簡單得讓人厭煩。更不用說瞧毙,設計師也要按順序干活胧华,你拿到那些圖片也是幾天之后了。所以我們還是來看看如何用Xcode 的Asset Catalog來處理這些麻煩事吧宙彪。
麻煩事No.1:“能改一下這個圖片的顏色嗎矩动?”
目前為止iOS已經(jīng)提供了一些相當復雜的方法來處理工程中的圖片,但很不幸的是释漆,卻沒有用來處理這種情況的方法悲没。我已經(jīng)數(shù)不清楚有多少次我們因為什么便捷性支持或者是客戶不喜歡而改變工程的顏色了。現(xiàn)在在工程中全局改變UIColor已經(jīng)不是什么難題了男图,但是我們還要改變工程中圖片的顏色示姿。這樣我們就不得不回去找已經(jīng)忙得要死的設計師了,就因為我們太懶而不去學學怎么用Photoshop享言。當然我們也可以寫代碼來完成峻凫,不過看起來相當復雜,而且還容易造成泄漏览露。在iOS7 之前荧琼,寫代碼改變圖片的顏色和下面差不多(還有很多其他的方法):
//改變圖片顏色
- (UIImage *)imageWithColor:(UIColor *)color
{
UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
CGContextRefcontext = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0, self.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextSetBlendMode(context, kCGBlendModeNormal);
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
CGContextClipToMask(context, rect, self.CGImage);
[color setFill];
CGContextFillRect(context, rect);
UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
在兩個大版本升級之后,我還能看到這樣的代碼差牛。在iOS7中命锄,我們有了imageWithRenderingMode
,這是UIImage的一個方法偏化,參數(shù)是有三個選項的枚舉值UIImageRenderingMode
脐恩。
typedef NS_ENUM(NSInteger, UIImageRenderingMode) {
UIImageRenderingModeAutomatic, // Use the default rendering mode for the context where the image is used
UIImageRenderingModeAlwaysOriginal, // Always draw the original image, without treating it as a template
UIImageRenderingModeAlwaysTemplate, // Always draw the image as a template image, ignoring its color information
} NS_ENUM_AVAILABLE_IOS(7_0);?
UIImageRenderingModeAlwaysOriginal 就和字面的意思一樣,這個模式告訴系統(tǒng)按照圖片文件原來的樣子渲染圖片侦讨。
UIImageRenderingModeAlwaysTemplate 這是最有意思的模式驶冒。首先會掃描你的圖片苟翻,然后從圖片中所有不透明的像素創(chuàng)建一個模板。這同時也會忽略圖片的所有顏色信息骗污。你可以使用UIView子類的tintColor屬性來給圖片填充你選擇的顏色崇猫。
UIImageRenderingModeAutomatic 這個模式由系統(tǒng)根據(jù)圖片的使用環(huán)境來決定如何渲染圖片。如果你的圖片是用在比如UITabBar需忿、UINavigationBar诅炉、UIToolbar 和UISegmentedControl這些地方,圖片使用AlwaysTemplate渲染模式屋厘。圖片用在其他的地方則會使用AlwaysOriginal渲染模式涕烧。
在了解了上面的內(nèi)容之后,之前我們改變圖片顏色的代碼就可以簡化成下面這樣的了:
UIImage *theImage;
[theImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
imageView.image = theImage;
imageView.tintColor = [UIColor color....];
是不是很神奇汗洒?用代碼改變圖片的顏色议纯,現(xiàn)在變得簡單多了。
等等仲翎,還沒完呢痹扇!其實不需要代碼也可以改變圖片的顏色。
從Xcode 6開始溯香,imageWithRenderingMode
已經(jīng)集成到Asset Catalog里了。如果你在Asset Catalog里選擇了一個圖片浓恶,在右邊的Attributes Inspector里玫坛,就可以像下圖那樣把Render As選項改成Template Image。
就是這么簡單包晰。甚至你還可以通過在Storyboard中湿镀,在Attributes Pane中改變UIImageView的tintColor屬性,來改變imageView中的圖片的顏色伐憾。
麻煩事No.2:“能給我這個的3X分辨率的圖嗎勉痴?”
這個的確很煩,因為每個app的每個設計師被問這個問題都至少一年了树肃。貌似蘋果每年都會增加一種新的屏幕分辨率蒸矛,今年我也持懷疑態(tài)度。隨著硬件技術的發(fā)展胸嘴,蘋果總是走在前沿雏掠,總是在盡可能地提高屏幕的ppi。很不幸劣像,這意味著我們不能直接在“預覽”中放大已有的圖片乡话,因為這會造成諸如圖片像素化和產(chǎn)生鋸齒等問題。通俗點耳奕,就是我們的圖片變丑了绑青,噁诬像!每次你叫設計師出一張已有圖片的3x分辨率圖,某個地方就又要死一只獨角獸了闸婴。這實際上也解釋了為什么現(xiàn)在看不到這種神奇的生物了坏挠。
所以去年我在WWDC上提到的最好的消息,就是Xcode 6 及以上版本支持在Asset Catalog中使用矢量PDF了掠拳。你的設計師知道這是什么意思癞揉,但是大致上,PDF是矢量元素的事實標準溺欧。矢量文件包含一個元素的很多元數(shù)據(jù)喊熟,用來告訴系統(tǒng)如何渲染這些內(nèi)容,而這些和屏幕分辨率無關姐刁。舉個通俗易懂例子芥牌,一個圓形的矢量PDF圖,當它渲染成5像素寬和渲染成5000000像素寬時是一樣清晰的聂使。
在iOS平臺壁拉,Xcode是在編譯時,根據(jù)你的矢量PDF圖的大小柏靶,生成1x弃理、2x和3x圖。如果你的PDF圖是45*45px屎蜓,那么Xcode會在編譯時生成下面3個PNG:
45*45px :1x設備用的(iPhone 3G and 3GS)
90*90px :2x或Retina顯示設備用的(iPhone 4, 4S, 5, 5S, and 6)
135*135px :3x設備用的(iPhone 6 Plus 及以上)
這也意味著當有更高的屏幕分辨率時痘昌,Xcode可以根據(jù)已有的矢量PDF放大圖片,這樣自動就支持以后的設備了炬转。還有辆苔,如果你是OS X開發(fā)者,那么矢量PDF就更好用了扼劈,OS X app完全支持矢量PDF驻啤,你可以用代碼縮放圖片而不會失真。
而你需要做的就是荐吵,找你的好基友設計師拿到這些矢量PDF文件骑冗,然后在Asset Catalog的Attribtues Pane中,在Scale Factor的下拉框中選擇Single Vector就行了捍靠。
你可以直接把PDF拖到Asset Catalog中沐旨,然后進行設置。
麻煩事No.3:“能給我新設備的啟動圖嗎榨婆?”
xcode8之后,已經(jīng)變成默認的方式了.
啟動圖對于app來說還是蠻重要的磁携。這是啟動app后最先看到的,它會給用戶一個app其余部分是如何設計的第一印象良风。如果我看到一個設計得很糟糕的啟動圖谊迄,我會認為app其他地方也好不到哪去闷供,當然這只是我的情況。對于我們那可憐的設計師來說统诺,每次有新設備出來時歪脏,他們都知道要放大啟動圖來支持新設備的分辨率。對于iPhone 6 和 iPhone 6 Plus粮呢,如果你沒有為這兩個設備準備對應的啟動圖婿失,那么app就會工作在放大模式。啟動圖還在Asset Catalog中啄寡,但是我建議把它拆出來豪硅,因為啟動圖也升級了。現(xiàn)在挺物,你可以使用LaunchScreen xibs懒浮。
在工程文件中,你可以指定app在啟動時加載的xib识藤,這樣你就不需要準備9張啟動圖了砚著。LaunchScreen.xib還支持自動布局,這樣我們就能分塊構(gòu)建啟動屏幕了痴昧。按如下這樣設置:
首先創(chuàng)建一個xib文件稽穆。你可以在如下圖所示的地方選擇Launch Screen類型的xib。
然后打開工程文件赶撰,選擇app的target秧骑,在Launch Screen file處選擇你的Launch Screen .xib文件。
盡可能地利用Launch Screen吧扣囊。你肯定不想被抓到在問設計師要一年后新出的手機平板的8x啟動圖。
麻煩事No.4:“能把這些按鈕的圖片拉長一點嗎绒疗?”
這種情況發(fā)生的概率比你想象的要高得多侵歇。對于一張pattern image或者是有圓角的圖片,考慮到有更大的屏幕吓蘑,你需要重新調(diào)整圖片的大小惕虑,以免圖片拉伸出現(xiàn)失真。Natasha發(fā)布了一篇很棒的文章來說明如何編程解決這個問題磨镶,但是我們也可以在Xcode 6的Asset Catalog中搞定它溃蔫。順便說一下,我強烈建議你在繼續(xù)往下讀之前琳猫,看一下Natasha的文章伟叛,這樣你就能理解到底發(fā)生了什么。免責聲明:下面的圖片等是直接從Natasha的文章中拷貝過來的脐嫂。Sorry统刮!
好了紊遵,我們繼續(xù)。
在之前侥蒙,一般用類似下面的代碼來獲得可改變大小的圖片:
let edgeInsets = UIEdgeInsets(top: 8.0, left: 8.0, bottom: 8.0, right: 8.0)
let backgroundButtonImage = UIImage(named:"purple_button")?.resizableImageWithCapInsets(edgeInsets)
purpleButton.setBackgroundImage(backgroundButtonImage, forState: .Normal)??
這將會得到一張和下面類似的圖片:
在運行時暗膜,會拉伸距離UIImageView的container的邊框8像素的中間部分,這樣就能保留圓角鞭衩,得到下面這樣的:
多虧了Xcode中Asset Catalog的slice和dice学搜,我們不需要代碼也能拉伸圖片。首先在Xcode中選中圖片论衍,然后點擊右下角的Show Slicing
:
你現(xiàn)在應該能看到slicing 面板和一個按鈕"Start Slicing"瑞佩。
在你點擊按鈕之后,會顯示下面的三個選項:
左邊的按鈕用于horizontal edge insets饲齐,右邊的按鈕用于vertical edge insets钉凌,中間的則是兩個都有。在我們的例子中要保留圓角捂人,所以我們按中間的按鈕御雕,告訴系統(tǒng)我們想要按鈕的中間在水平和垂直方向拉伸。在按下按鈕之后滥搭,就能看到一些可以拖動的細條酸纲,這可以設置從哪里開始拉伸圖片。
系統(tǒng)會保留深紫色的區(qū)域瑟匆,淺紫色的區(qū)域會被拉伸闽坡。
更厲害的是,Xcode自動找到了圓角愁溜,所以我們不需要設置從哪里開始拉伸圖片疾嗅。最后別忘了在Attribtues pane中設置圖片是可拉伸的。
如果我是你的話冕象,我就會嘗試并習慣這個功能代承。有了這個無價之寶,你就不用再在resizableImageWithCapInsets
方法中填寫那些神奇的數(shù)字了渐扮,也能幫助你分離view邏輯和app邏輯论悴。
結(jié)論
我很確定,我們開發(fā)者幾乎每天都還會做很多其他事去麻煩設計師們墓律,但至少我們能多用用這些功能膀估,讓他們稍微休息一會兒。畢竟編程能解決一切問題耻讽,何樂而不為呢察纯?