轉(zhuǎn)載自:http://www.cnblogs.com/snake-hand/p/3190021.html
在調(diào)用視圖的drawRect:方法之前,UIKit 會自動對描畫環(huán)境進行配置,使左上角成為坐標(biāo)系統(tǒng)的原點,在這個環(huán)境中發(fā)生的Quartz調(diào)用都可以正確地在視圖中描畫。
視圖對象通過frame、bounds、和center屬 性聲明來跟蹤自己的大小和位置。frame 屬性包含一個矩形,即邊框矩形,用于指定視圖相對于其父視圖坐標(biāo)系統(tǒng)的位置和大小。bounds 屬性也包含一個矩形,即邊界矩形,負(fù)責(zé)定義視圖相對于本地坐標(biāo)系統(tǒng)的位置和大小。雖然邊界矩形的原點通常被設(shè)置為(0, 0),但這并不是必須的。center 屬性包含邊框矩形的中心點。
當(dāng)您在代碼中通過initWithFrame:方法創(chuàng)建一個視圖對象時,其frame 屬性就會被設(shè)置。該方法同時也將bounds 矩形的原點初始化為(0.0, 0.0),大小則和視圖的邊框相同。然后center 屬性會被設(shè)置為邊框的中心點。缺省情況下,視圖的邊框并不會被父視圖的邊框裁剪。如果您希望讓一個視圖裁剪其子視圖,需要將其clipsToBounds屬性設(shè)置為YES。
舉例來說,UIView類中包含一個transform屬性聲明,您可以通過它來對整個視圖實行各種類型的平移、比例縮放、和變焦縮放效果。缺省情況下,這個屬性的值是一個恒等變換,不會改變視圖的外觀。在加入變換之前,首先要得到該屬性中存儲的CGAffineTransform結(jié)構(gòu),用相應(yīng)的Core Graphics 函數(shù)實行變換,然后再將修改后的變換結(jié)構(gòu)重新賦值給視圖的transform 屬性。
視圖的contentMode屬性決定了邊界變化和縮放操作作用到視圖上產(chǎn)生的效果。缺省情況下,這個屬性的值被設(shè)置為UIViewContentModeScaleToFill,意味著視圖內(nèi)容總是被縮放,以適應(yīng)新的邊框尺寸。不同的UIViewContentMode常量(比如UIViewContentModeTop和UIViewContentModeBottomRight)可以使當(dāng)前的內(nèi)容在視圖的不同角落或沿著視圖的不同邊界顯示,還有一種模式可以將內(nèi)容顯示在視圖的中心。
當(dāng)您希望在應(yīng)用程序中實現(xiàn)尺寸可調(diào)整的控件時,請務(wù)必考慮使用內(nèi)容模式。內(nèi)容模式通常有助于避免視圖內(nèi)容的描畫,但是當(dāng)您希望對縮放和尺寸調(diào)整過程中的視圖外觀進行特別的控制時,也可以使用UIViewContentModeRedraw模式如果視圖的autoresizesSubviews屬性聲明被設(shè)置為YES,則其子視圖會根據(jù)autoresizingMask屬性的值自動進行尺寸調(diào)整。否則,應(yīng)用程序就必須通過重載layoutSubviews方法來提供自己的實現(xiàn)。如果要使一個視圖和其父視圖左下角的相對位置保持不變, 可以加入UIViewAutoresizingFlexibleRightMargin和UIViewAutoresizingFlexibleTopMargin常量,并將結(jié)果賦值給autoresizingMask屬性。當(dāng)同一個軸向有多個部分被設(shè)置為可變時,尺寸調(diào)整的裕量會被平均分配到各個部分上。UIViewAutoresizingNone這個常量如果被設(shè)置,視圖將不進行自動尺寸調(diào)整。
UIViewAutoresizingFlexibleHeight這個常量如果被設(shè)置,視圖的高度將和父視圖的高度一起成比例變化。否則,視圖的高度將保持不變。
UIViewAutoresizingFlexibleWidth這個常量如果被設(shè)置,視圖的寬度將和父視圖的寬度一起成比例變化。否則,視圖的寬度將保持不變。
UIViewAutoresizingFlexibleLeftMargin這個常量如果被設(shè)置,視圖的左邊界將隨著父視圖寬度的變化
而按比例進行調(diào)整。否則,視圖和其父視圖的左邊界的相對位置將保持不變。
UIViewAutoresizingFlexibleRightMargin這個常量如果被設(shè)置,視圖的右邊界將隨著父視圖寬度的變化
而按比例進行調(diào)整。否則,視圖和其父視圖的右邊界的相對位置將保持不變。
UIViewAutoresizingFlexibleBottomMargin這個常量如果被設(shè)置,視圖的底邊界將隨著父視圖高度的變化
而按比例進行調(diào)整。否則,視圖和其父視圖的底邊界的相對位置將保持不變。
UIViewAutoresizingFlexibleTopMargin這個常量如果被設(shè)置,視圖的上邊界將隨著父視圖高度的變化
而按比例進行調(diào)整。否則,視圖和其父視圖的上邊界的相對位
置將保持不變。
如果您通過Interface Builder配置視圖,則可以用Size 查看器的Autosizing控 制來設(shè)置每個視圖的自動尺寸調(diào)整行為。上圖中的靈活寬度及高度常量和Interface Builder 中位于同樣位置的彈簧具有同樣的行為,但是空白常量的行為則是正好相反。換句話說,如果要將靈活右空白的自動尺寸調(diào)整行為應(yīng)用到Interface Builder 的某個視圖,必須使相應(yīng)方向空間的Autosizing控制為空,而不是放置一個支柱。
如果視圖的autoresizesSubviews屬性被設(shè)置為NO,則該視圖的直接子視圖的所有自動尺寸調(diào)整行為將被忽略。類似地, 如果一個子視圖的自動尺寸調(diào)整掩碼被設(shè)置為
UIViewAutoresizingNone,則該子視圖的尺寸將不會被調(diào)整,因而其直接子視圖的尺寸也不會被調(diào)整。
視圖層次中的父-子關(guān)系可以幫助我們定義應(yīng)用程序中負(fù)責(zé)處理觸摸事件的對象鏈創(chuàng)建一個新的視圖對象時,需要為其分配內(nèi)存,并向該對象發(fā)送一個initWithFrame:消息,以對其進行初始化。舉例來說,如果您要創(chuàng)建一個新的UIView類的實例作為其它視圖的容器,則可以使用下面的代碼:
CGRectviewRect = CGRectMake(0, 0, 100, 100);
UIView* myView = [[UIView alloc]initWithFrame:viewRect];
在iPhone 程序中,有兩個地方最常用于創(chuàng)建視圖和子視圖, 它們是應(yīng)用程序委托對象的applicationDidFinishLaunching:方法和視圖控制器的loadView方法。
調(diào)用父視圖的addSubview:方法來添加視圖,該方法將一個視圖添加到子視圖列表的最后。
調(diào)用父視圖的insertSubview:...方法可以在父視圖的子視圖列表中間插入視圖。
調(diào)用父視圖的bringSubviewToFront: 、sendSubviewToBack: 、或
exchangeSubviewAtIndex:withSubviewAtIndex:方法可以對父視圖的子視圖進行重新排序。使用這些方法比從父視圖中移除子視圖并再次插入要快一些。
調(diào)用子視圖(而不是父視圖)的removeFromSuperview方法可以將子視圖從父視圖中移除。
創(chuàng)建一個帶有視圖的窗口
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// Create the window object and assign it to the
// window instance variable of the application delegate.
window = [[UIWindow alloc] initWithFrame:[[UIScreenmainScreen]? bounds]];
window.backgroundColor= [UIColor whiteColor];
// Create a simple red square
CGRect redFrame = CGRectMake(10, 10, 100, 100);
UIView *redView = [[UIView alloc] initWithFrame:redFrame];
redView.backgroundColor = [UIColor redColor];
// Create a simple blue square
CGRect blueFrame = CGRectMake(10, 150, 100, 100);
UIView *blueView = [[UIView alloc] initWithFrame:blueFrame];
blueView.backgroundColor = [UIColor blueColor];
// Add the square views to the window
[window addSubview:redView];
[window addSubview:blueView];
// Once added to the window, release the views to avoid the
// extra retain count on each of them.
[redView release];
[blueView release];
// Show the window.
[window makeKeyAndVisible];
}
當(dāng)您為某個視圖添加子視圖時,UIKit 會向相應(yīng)的父子視圖發(fā)送幾個消息,通知它們當(dāng)前發(fā)生的狀態(tài)變化。您可以在自己的定制視圖中對諸如willMoveToSuperview: 、willMoveToWindow: 、willRemoveSubview: 、didAddSubview: 、didMoveToSuperview、和didMoveToWindow這樣的方法進行重載,以便在事件發(fā)生的前后進行必要的處理,并根據(jù)發(fā)生的變化更新視圖的狀態(tài)信息。
在視圖層次建立之后,您可以通過視圖的superview屬性來取得其父視圖,或者通過subviews屬性取得視圖的子視圖。您也可以通過isDescendantOfView:方法來判定一個視圖是否在其父視圖的視圖層中。一個視圖層次的根視圖沒有父視圖,因此其superview 屬性被設(shè)置為nil。對于當(dāng)前被顯示在屏幕上的視圖,窗口對象通常是整個視圖層次的根視圖。
UIView 類定義了下面這些方法,用于在不同的視圖本地坐標(biāo)系統(tǒng)之間進行坐標(biāo)轉(zhuǎn)換:
convertPoint:fromView:
convertRect:fromView:
convertPoint:toView:
convertRect:toView:
UIWindow 的版本則使用窗口坐標(biāo)系統(tǒng)。
convertPoint:fromWindow:
convertRect:fromWindow:
convertPoint:toWindow:
convertRect:toWindow:
UIView 類中包含一個tag屬性。借助這個屬性,您可以通過一個整數(shù)值來標(biāo)識一個視圖對象。您可以通過這個屬性來唯一標(biāo)識視圖層次中的視圖,以及在運行時進行視圖的檢索(基于tag 標(biāo)識的檢索比您自行遍歷視圖層次要快)。tag 屬性的缺省值為0。您可以通過UIView 的viewWithTag:方法來檢索標(biāo)識過的視圖
動畫塊從調(diào)用UIView 的beginAnimations:context:類方法開始,而以調(diào)用commitAnimations類 方法作為結(jié)束。在這兩個調(diào)用之間,您可以配置動畫的參數(shù)和改變希望實行動畫的屬性值。一旦調(diào)用commitAnimations 方法,UIKit 就會開始執(zhí)行動畫,即把給定屬性從當(dāng)前值到新值的變化過程用動畫表現(xiàn)出來。動畫塊可以被嵌套,但是在最外層的動畫塊提交之前,被嵌套的動畫不會被執(zhí)行。
frame 視圖的邊框矩形,位于父視圖的坐標(biāo)系中。
bounds 視圖的邊界矩形,位于視圖的坐標(biāo)系中。
center 邊框的中心,位于父視圖的坐標(biāo)系中。
transform 視圖上的轉(zhuǎn)換矩陣,相對于視圖邊界的中心。
alpha 視圖的alpha 值,用于確定視圖的透明度。
用setAnimationStartDate:方法來設(shè)置動畫在commitAnimations 方法返回之后的發(fā)生日期。缺省行為是使動畫立即在動畫線程中執(zhí)行。
用setAnimationDelay:方法來設(shè)置實際發(fā)生動畫和commitAnimations 方法返回的時間點之間的間隔。
用setAnimationDuration:方法來設(shè)置動畫持續(xù)的秒數(shù)。
用setAnimationCurve:方法來設(shè)置動畫過程的相對速度,比如動畫可能在啟示階段逐漸加速,而在結(jié)束階段逐漸減速,或者整個過程都保持相同的速度。
用setAnimationRepeatCount:方法來設(shè)置動畫的重復(fù)次數(shù)。
用setAnimationRepeatAutoreverses:方法來指定動畫在到達目標(biāo)值時是否自動反向播放。您可以結(jié)合使用這個方法和setAnimationRepeatCount:方法,使各個屬性在初始值和目標(biāo)值之間平滑切換一段時間。
您可以通過UIView 的setAnimationDelegate: 類方法來設(shè)置委托, 并通過setAnimationWillStartSelector: 和setAnimationDidStopSelector:方法來指定接收消息的選擇器方法。消息處理方法的形式如下:
- (void)animationWillStart:(NSString *)animationID context:(void *)context;
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void
*)context;
上面兩個方法的animationID 和context 參數(shù)和動畫塊開始時傳beginAnimations:context:方法的參數(shù)相同:animationID- 應(yīng)用程序提供的字符串,用于標(biāo)識一個動畫塊中的動畫。
context- 也是應(yīng)用程序提供的對象,用于向委托對象傳遞額外的信息。
setAnimationDidStopSelector:選擇器方法還有一個參數(shù)—即一個布爾值。如果動畫順利完成,沒有被其它動畫取消或停止,則該值為YES。
任何時候,當(dāng)視圖的布局發(fā)生改變時,UIKit 會激活每個視圖的自動尺寸調(diào)整行為,然后調(diào)用各自的layoutSubviews方法,使您有機會進一步調(diào)整子視圖的幾何尺寸。
您的應(yīng)用程序調(diào)用視圖的setNeedsLayout或layoutIfNeeded方法來強制進行布局。
您的應(yīng)用程序調(diào)用視圖背后的層對象的setNeedsLayout方法來強制進行布局。
您也可以用layoutSubviews方法來調(diào)整作為子層鏈接到視圖層的定制CALayer對象有些時候,應(yīng)用程序數(shù)據(jù)模型的變化會影響到相應(yīng)的用戶界面。為了反映這些變化,您可以將相應(yīng)的視圖標(biāo)識為需要刷新(通過調(diào)用setNeedsDisplay或setNeedsDisplayInRect:方法)
您可以通過改變視圖的hidden屬性聲明來隱藏或顯示視圖
初始化一個視圖的子類
- (id)initWithFrame:(CGRect)aRect {
self = [super initWithFrame:aRect];
if (self) {
// setup the initial properties of
the view
...
}
return self;
}
在iPhone OS 中,裝載nib 的代
碼并不通過initWithFrame:方法來實例化新的視圖對象,而是通過NSCoding 協(xié)議定義的initWithCoder:方法來進行。
drawRect:方法的一個簡單實現(xiàn),即在視圖邊界描畫一個10像素寬的紅色邊界。由于UIKit 描畫操作的實現(xiàn)也是基于Quartz,所以您可以像下面這樣混合使用不同的描畫調(diào)用來得到期望的結(jié)果。
- (void)drawRect:(CGRect)rect {
CGContextRefcontext =UIGraphicsGetCurrentContext();
CGRect myFrame = self.bounds;
CGContextSetLineWidth(context, 10);
[[UIColor redColor] set];
UIRectFrame(myFrame);?
}
處理觸摸事件的視圖通常需要實現(xiàn)下面的所有方法
touchesBegan:withEvent:
touchesMoved:withEvent:
touchesEnded:withEvent:
touchesCancelled:withEvent:
激活多點觸摸事件:multipleTouchEnabled屬性聲明設(shè)置為YES。
您可以通過改變視圖的userInteractionEnabled屬性值來控制視圖是否可以對事件進行處理。
還可以使用UIApplication 對象的beginIgnoringInteractionEvents和endIgnoringInteractionEvents方法
UIKit 會通過UIView 的hitTest:withEvent:和pointInside:withEvent:方法來確定觸摸事件是否發(fā)生在指定的視圖上。