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