一、View和Window簡(jiǎn)介
在iOS中摔认,我們用window和view來呈現(xiàn)應(yīng)用的內(nèi)容逆皮。事實(shí)上window本身不能呈現(xiàn)任何可視的內(nèi)容,但是它可以為view提供基本的容器功能参袱。view相當(dāng)于定義了window中的一塊用于顯示內(nèi)容的區(qū)域电谣。例如:用來顯示圖片、文字抹蚀、圖形或者以上幾者的組合的view剿牺。你也可以用view來組織和管理其他view。
每個(gè)應(yīng)用都至少有一個(gè)window和一個(gè)view組成环壤。UIKit和其他系統(tǒng)框架提供了一些預(yù)定義的view:從最簡(jiǎn)單的button晒来、text label到復(fù)雜的table view、picker view郑现、scroll view湃崩。當(dāng)預(yù)定義的view不能滿足你的需求的時(shí)候荧降,你還能創(chuàng)建自定義view來管理view的繪制和事件處理。
view是UIView類(或其子類)的實(shí)例竹习,它管理應(yīng)用的window中的一塊矩形區(qū)域誊抛。view負(fù)責(zé)繪制內(nèi)容、處理事件整陌、管理subview的布局拗窃。繪制內(nèi)容涉及到使用Core Graphics、OpenGL ES或者UIKit來繪制形狀泌辫、圖片和文字随夸。view同時(shí)還負(fù)責(zé)處理對(duì)其矩形區(qū)域內(nèi)發(fā)生的觸摸或者手勢(shì)事件。在view的層級(jí)結(jié)構(gòu)(hierarchy)中震放,parent view負(fù)責(zé)他們的child view的布局并且可以動(dòng)態(tài)的隨時(shí)調(diào)整布局宾毒,這在界面旋轉(zhuǎn)或者實(shí)現(xiàn)界面動(dòng)畫的情況下尤其有用。
window是UIWindow類的實(shí)例并且用于處理應(yīng)用總的界面呈現(xiàn)殿遂。一般來說應(yīng)用的window基本不會(huì)變化:當(dāng)一個(gè)window被創(chuàng)建后诈铛,它就待在那兒,只有window里的view會(huì)經(jīng)常發(fā)生變化墨礁〈敝瘢基本上一個(gè)應(yīng)用就一個(gè)window,如果設(shè)備接入了外部顯示恩静,那么應(yīng)用會(huì)創(chuàng)建第二個(gè)window用于在外部顯示上呈現(xiàn)內(nèi)容焕毫。
動(dòng)畫用來為用戶提供內(nèi)容變化的視覺反饋。系統(tǒng)定義了在模態(tài)化view和不同view之間切換的標(biāo)準(zhǔn)動(dòng)畫驶乾。當(dāng)然view的很多屬性也可以使用動(dòng)畫效果邑飒,例如:view的透明度、位置级乐、背景色等疙咸。如果你直接使用view底層的Core Animation Layer,你還能做出更多炫酷的動(dòng)畫效果风科。
Interface Builder是一個(gè)可視化編輯window和view的工具撒轮。使用IB,你的view都存放在一個(gè)nib(xib)文件中丐重。你可以把nib文件想像成是存儲(chǔ)view和其他對(duì)象的序列化資源文件。當(dāng)你在運(yùn)行時(shí)load一個(gè)nib文件的時(shí)候杆查,里面的對(duì)象會(huì)重新組成到內(nèi)存中并且可以被代碼操作扮惦。
二、View和Window的結(jié)構(gòu)
1. View結(jié)構(gòu)基礎(chǔ)
view和Core Animation Layer配合來處理view的繪制和動(dòng)畫效果亲桦。每個(gè)view的背后都有一個(gè)layer對(duì)象(通常是CALayer類的實(shí)例)負(fù)責(zé)這個(gè)view的繪制和動(dòng)畫效果崖蜜。大多數(shù)情況下你只需要和UIView的接口打交道浊仆,只有在某些特定的情況下你才需要操作layer對(duì)象。
為了幫助理解view和layer之間的關(guān)系豫领,可以參考圖1-1抡柿。在圖1-1中我們可以看到UIBarButtonItem是沒有l(wèi)ayer的,因?yàn)樗怯蒛IToolbar繪制出來的等恐,并非一個(gè)獨(dú)立的view洲劣。
2. View的層級(jí)結(jié)構(gòu)和Subview管理
當(dāng)一個(gè)view包含另一個(gè)view的時(shí)候,兩個(gè)view之間就有了parent-child關(guān)系课蔬。child view就叫subview囱稽,parent view就叫superview。
視覺上二跋,subview的內(nèi)容遮蓋superview全部或部分的內(nèi)容空間战惊。如果subview是不透明的,那他就徹底遮蓋了superview對(duì)應(yīng)的部分扎即。如果subview是部分透明的吞获,那這兩個(gè)view的內(nèi)容就會(huì)混合在一起顯示(想象成高斯模糊的那種效果)。每個(gè)superview將它的subview存儲(chǔ)在一個(gè)排序過的數(shù)組里谚鄙。越晚添加的或者順序越大的顯示在越上面各拷。
superview - subview的這種關(guān)系也會(huì)影響到一些view的行為。例如:改變superview的大小也會(huì)使subview的大小和位置發(fā)生改變襟锐。還包括改變superview的透明度撤逢、改變superview的坐標(biāo)系統(tǒng)。
view的層級(jí)關(guān)系還影響到事件的傳遞粮坞。當(dāng)某個(gè)view中發(fā)生了觸摸事件蚊荣,如果當(dāng)前的這個(gè)view無法處理,事件會(huì)順著view的層級(jí)向上傳遞莫杈。特定的view還會(huì)把事件傳遞給responder對(duì)象互例,例如一個(gè)view controller。如果事件最終傳遞到最頂級(jí)的application對(duì)象筝闹,通常這個(gè)事件就被丟棄了媳叨。
3. View的繪制周期
UIView使用按需繪制的模式來呈現(xiàn)內(nèi)容。當(dāng)一個(gè)view首次呈現(xiàn)在屏幕上時(shí)关顷,系統(tǒng)會(huì)要求它繪制一下它的內(nèi)容糊秆。然后系統(tǒng)會(huì)捕捉一張快照,并且一直使用它议双。如果你不改變view的內(nèi)容痘番,那么view的繪制代碼就不會(huì)被再次執(zhí)行。當(dāng)你改變了view的顯示內(nèi)容,你應(yīng)該使用view的setNeedsDisplay或setNeedsDisplayInRect方法來要求重繪汞舱。如果你是自定義UIView的子類伍纫,那么通常你應(yīng)該重載drawRect方法來繪制你的view。你也有其他方法來繪制view昂芜,例如直接在layer上繪制莹规,但通常你應(yīng)該重載drawRect來實(shí)現(xiàn)自定義view的繪制。
4. View的Content Mode
每個(gè)view有一個(gè)content mode泌神,當(dāng)view的幾何形狀發(fā)生變化時(shí)良漱,它用來控制view的內(nèi)容是否需要重繪或者將如何改變。
當(dāng)你進(jìn)行如下操作時(shí)腻扇,content mode將會(huì)起作用:
- 改變view的frame或者bounds的寬高
- view的transform屬性含有scale factor
默認(rèn)的content mode是UIViewContentModeScaleToFill债热。它會(huì)使view的內(nèi)容縮放以適應(yīng)新的frame尺寸。圖1-2顯示了各種content mode下的內(nèi)容縮放情況幼苛。
content mode有助于避免不必要的內(nèi)容重繪窒篱,當(dāng)然你也可以設(shè)置content mode為UIViewContentModeRedraw來強(qiáng)制view在每次縮放或尺寸改變時(shí)重繪(調(diào)用drawRect方法),但是通常你應(yīng)當(dāng)避免這么做舶沿。
5. 可拉伸的View
你可以指定view的某塊區(qū)域?yàn)榭衫烨奖@樣當(dāng)view的尺寸改變的時(shí)候,只有可拉伸的區(qū)域會(huì)受到影響括荡。一般會(huì)在按鈕上使用這種技術(shù)高镐。圖1-3顯示了可拉伸時(shí),view是如何變化的畸冲。
使用view的content stretch屬性來指定可拉伸的區(qū)域嫉髓。這個(gè)屬性接受一個(gè)rectangle值來表示可拉伸區(qū)域,并且這個(gè)值會(huì)歸一化到0.0 - 1.0邑闲。這樣當(dāng)拉伸發(fā)生時(shí)算行,系統(tǒng)可以用view的當(dāng)前bounds以及scale factor乘以這個(gè)歸一化的值來決定如何縮放。另外view的content mode也會(huì)影響拉伸苫耸。只有UIViewContentModeScaleToFill州邢、UIVieweContentModeScaleAspectFit和UIViewContentModeScaleAspectFill這幾個(gè)content mode才會(huì)出發(fā)拉伸。
推薦在設(shè)置view的背景時(shí)使用一個(gè)可拉伸的UIImage對(duì)象來實(shí)現(xiàn)拉伸
6. 內(nèi)置動(dòng)畫支持
UIView類的一些屬性是支持半自動(dòng)動(dòng)畫的褪子。你只需要:
- 告訴UIKit你要使用動(dòng)畫了量淌!
- 改變這些屬性的值
這些屬性有:
- frame —— 位置和尺寸的動(dòng)畫
- bounds —— 尺寸動(dòng)畫
- center —— 位置動(dòng)畫
- transform —— 旋轉(zhuǎn)和縮放動(dòng)畫
- alpha —— 改變透明度
- backgroundColor —— 改變背景色
- cententStretch —— 改變view如何拉伸
一般來說,viewcontroller之間過度時(shí)會(huì)使用動(dòng)畫嫌褪。當(dāng)然你也可以直接在兩個(gè)view之間使用動(dòng)畫呀枢。另外,除了使用UIKit類來實(shí)現(xiàn)動(dòng)畫笼痛,你還能使用Core Animation Layer來實(shí)現(xiàn)動(dòng)畫裙秋,它能提供更多的時(shí)間和屬性上的控制。
下篇 View編程指南(二)