UIView與UIWindow
-
Uiview需要一個窗口UIWindow來展示頁面,而UIWindow類似于一個Uiview.
- 1.調(diào)用[parentView addSubview:childview]來添加基于該視圖或者該窗口的子視圖,新創(chuàng)建的視圖順序顯示在最前面.
- 2.調(diào)用[parentView subviews]來查詢基于該視圖或者該窗口下的所有的子視圖.順序為從后到前, 即添加順序.
- 3.調(diào)用[view removeFromSuperview]可以從該主視圖(可以是窗口)中刪除.
- 4.調(diào)用[parentView exchangeSubviewAtIndex:I withSubviewAtIndex:j]來重新派訊,修改j索引下的子視圖為i索引.也可以使用bringSubviewToFront:或者sendSubviewToBack:將視圖前移或者后移.
- 5.使用setTag:給子視圖添加標記.做這個標記可以在父視圖中調(diào)用[parentView viewWithTag:]可以搜索到該標記的子視圖.也可以作為一個區(qū)分的意思(當前太多視圖或者控件時候).
-
UIWindow的作用:
- 和Mac OS X的應用程序有所不同,iPhone應用程序通常只有一個窗口,表示為一個UIWindow類的實例。您的應用程序在啟動時創(chuàng)建這個窗口(或者從nib文件進行裝載),并往窗口中加入一或多個視圖,然后將它顯示出來。窗口顯示出來之后,您很少需要再次引用它。
- 在iOS中,窗口對象并沒有像關(guān)閉框或標題欄這樣的視覺裝飾,用戶不能直接對其進行關(guān)閉或其它操作。所有對窗口的操作都需要通過其編程接口來實現(xiàn)。應用程序可以借助窗口對象來進行事件傳遞。窗口對象會持續(xù)跟蹤當前的第一響應者對象,并在UIApplication對象提出請求時將事件傳遞它。
- UIWindow類的繼承關(guān)系。在Mac OS X中,NSWindow的父類是NSResponder;而在iOS中,UIWindow的父類是UIView。因此,窗口在iOS中也是一個視圖對象。不管其起源如何,您通常可以將iOS上的窗口和Mac OS X的窗口同樣對待。也就是說,您通常不必直接操作UIWindow對象中與視圖有關(guān)的屬性變量。
- 在創(chuàng)建應用程序窗口時,您應該總是將其初始的邊框尺寸設(shè)置為整個屏幕的大小。如果您的窗口是從nib文件裝載得到,Interface Builder并不允許創(chuàng)建比屏幕尺寸小的窗口;然而,如果您的窗口是通過編程方式創(chuàng)建的,則必須在創(chuàng)建時傳入期望的邊框矩形。除了屏幕矩形之外,沒有理由傳入其它邊框矩形。屏幕矩形可以通過UIScreen對象來取得,具體代碼如下所示:
UIWindow* aWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
雖然iOS支持將一個窗口疊放在其它窗口的上方,但是您的應用程序永遠不應創(chuàng)建多個窗口。系統(tǒng)自身使用額外的窗口來顯示系統(tǒng)狀態(tài)條、重要的警告、以及位于應用程序窗口上方的其它消息。如果您希望在自己的內(nèi)容上方顯示警告,可以使用UIKit提供的警告視圖,而不應創(chuàng)建額外的窗口。
UIView是作用
視圖是UIView類的實例,負責在屏幕上定義一個矩形區(qū)域。在iPhone的應用程序中,視圖在展示用戶界面及響應用戶界面交互方面發(fā)揮關(guān)鍵作用。每個視圖對象都要負責渲染視圖矩形區(qū)域中的內(nèi)容,并響應該區(qū)域中發(fā)生的觸碰事件。這一雙重行為意味著視圖是應用程序與用戶交互的重要機制。在一個基于模型-視圖-控制器(MVC)的應用程序中,視圖對象明顯屬于視圖部分。
除了顯示內(nèi)容和處理事件之外,視圖還可以用于管理一或多個子視圖。子視圖是指嵌入到另一視圖對象邊框內(nèi)部的視圖對象,而被嵌入的視圖則被稱為父視圖或超視圖。視圖的這種布局方式被稱為視圖層次,一個視圖可以包含任意數(shù)量的子視圖,通過為子視圖添加子視圖的方式,視圖可以實現(xiàn)任意深度的嵌套。視圖在視圖層次中的組織方式?jīng)Q定了在屏幕上顯示的內(nèi)容,原因是子視圖總是被顯示在其父視圖的上方;這個組織方法還決定了視圖如何響應事件和變化。每個父視圖都負責管理其直接的子視圖,即根據(jù)需要調(diào)整它們的位置和尺寸,以及響應它們沒有處理的事件。
-
由于視圖對象是應用程序和用戶交互的主要途徑,所以需要在很多方面發(fā)揮作用,下面是其中的一小部分:
- 描畫和動畫
- 視圖負責對其所屬的矩形區(qū)域進行描畫。
- 某些視圖屬性變量可以以動畫的形式過渡到新的值。
- 布局和子視圖管理
- 視圖管理著一個子視圖列表。
- 視圖定義了自身相對于其父視圖的尺寸調(diào)整行為。
- 必要時,視圖可以通過代碼調(diào)整其子視圖的尺寸和位置。
- 視圖可以將其坐標系統(tǒng)下的點轉(zhuǎn)換為其它視圖或窗口坐標系統(tǒng)下的點。
- 事件處理
- 視圖可以接收觸摸事件。
- 視圖是響應者鏈的參與者。
- 描畫和動畫
在iPhone應用程序中,視圖和視圖控制器緊密協(xié)作,管理若干方面的視圖行為。視圖控制器的作用是處理視圖的裝載與卸載、處理由于設(shè)備旋轉(zhuǎn)導致的界面旋轉(zhuǎn),以及和用于構(gòu)建復雜用戶界面的高級導航對象進行交互。
- UIKit的視圖類
- UIView類定義了視圖的基本行為,但并不定義其視覺表示。相反,UIKit通過其子類來為像文本框、按鍵、及工具條這樣的標準界面元素定義具體的外觀和行為。
- 除了UIView和UIControl類是例外,這個框圖中的大多數(shù)視圖都設(shè)計為可直接使用,或者和委托對象結(jié)合使用。
CALayer
- CALayer直接繼承于NSObject,因為缺少UIResponder的支持,所以CALayer不能響應任何用戶事件
- 每個UIView都有CALayer,即UIView.layer,其所有視覺效果都是在這個layer上進行的。可以認為UIView注重于處理用戶事件,而CALayer則注重于顯示效果。CALayer是繪制內(nèi)容的,不處理事件響應,與UIView是相互依賴的,依賴于UIView來顯示繪制內(nèi)容,UIView依賴于CALayer來提供內(nèi)容
UIWindow
UIwindow繼于UIView。UIWindow對象是所有UIView的根,管理和協(xié)調(diào)應用程序的顯示。
UIWindow類是UIView的子類,可以看作是特殊的UIView。一般應用程序只有一個UIWindow對象,但可以手動創(chuàng)建多個添加到程序中,即使有多個UIWindow對象,也只有一個UIWindow可以接受到用戶的觸屏事件。
-
UIWindow主要起三個作用:
一是作為容器提供一個區(qū)域來顯示UIView,包含程序所有要顯示的視圖
二是將事件(event)的分發(fā)給UIView(傳遞觸摸消息到其他的UIView或其他對象)
三是與UIViewController協(xié)同工作,完成設(shè)備方向旋轉(zhuǎn)的支持
創(chuàng)建一個UIWindow:
1.創(chuàng)建一個全頻的window
self.window = [[UIWindow alloc] initWithFram:[UIScreen mainScreen].bounds];
2.在window中放入根控制器
self.window.rootViewControl = rootViewControl;
3.將window設(shè)置為keyWindow并顯示window
[self.window makeKeyAndVisible];
- 獲取當前的keyWindow
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
- UIScreen可以看成就是手機屏幕,它提供了一個畫布,可以在上面畫各種視圖控件,可以通過[[UIScreen mainScreen] bounds]來獲取屏幕尺寸.
iphone屏幕分辨率:
iphone4前的設(shè)備:320*480
iphone4和4s:640*960
iphone5和5s:640*1136
iphone6:750*1334
iphone6p:1242*2208
ipad ipad2:1024*768
ipad3和4 ipad4:2048*1536
ipad mini:1024*768
UIView
- UIView對象定義了一個屏幕上的一個矩形區(qū)域,同時處理該區(qū)域的繪制和觸屏事件。
- 可以在這個區(qū)域內(nèi)繪制圖形和文字,還可以接收用戶的操作。一個UIView的實例可以包含和管理若干個子UIView。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 100, 100)];
myView.backgroundColor=[UIColor redColor];
[self.view addSubview:myView];
}
- UIView中常用的結(jié)構(gòu)體:
CGPoint point = CGPointMake(x,y);//左上角坐標的位置
CGSize size = CGSizeMake(width,height);//大小
CGRect rect = CGRectMake(x,y,width,height);//位置和大小 ```
- UIView的常用屬性:
```objc
frame: 相對父視圖的位置和大小
bounds:相對自身的位置和大小,所以bounds的x和y永遠為0
center:子視圖的中點坐標相對父視圖的位置
transform:可以通過這個屬性控制視圖的放大縮小和旋轉(zhuǎn)
superview:獲取父視圖
subviews:獲取所有子視圖
alpha:視圖的透明度(0-1)
tag:視圖的標志,設(shè)置了tag后,可以通過viewWithTag方法拿到這個視圖
userInteractionEnabled:是否響應用戶事件
- 通過transform屬性來對視圖進行縮放,旋轉(zhuǎn)
CGAffineTransform transform = rootView.transform;
rootVIew.transform = CGAffineTransformMakeScale(0.5, 0.5);//縮放
rootView.transform = CGAffineTransformScale(transform,0.5,0.5)//在原來的基礎(chǔ)上再縮放
rootView.transform = CGAffineTransformMakeRotation(M_2_PI);//旋轉(zhuǎn)傳入的角度是弧度制的
rootView.transform = CGAffineTransformRotate(transform,M_PI_4);
rootView.transform = CGAffineTransformMakeTranslation(100, 100);//平移
rootView.transform = CGAffineTransformTranslate(transform, 100, 100);
- UIView的常用方法:
- (void)removeFromSuperview;將視圖從父視圖中移除
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;插入一個視圖到指定位置,視圖越在下面,index越小
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;將index1和index2位置的兩個視圖互換位置
- (void)addSubview:(UIView *)view;添加視圖到父視圖
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;插入視圖到指定視圖的下面
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;插入視圖到指定視圖上面
- (void)bringSubviewToFront:(UIView *)view;把視圖移到最頂層
- (void)sendSubviewToBack:(UIView *)view;把視圖移到最底層
- (UIView *)viewWithTag:(NSInteger)tag; 根據(jù)視圖的tag屬性找到搜索視圖
- 通過UIView的屬性產(chǎn)生一些基本動畫
UIVIew中支持動畫的屬性有以下幾個:
frame:可以通過frame來改變視圖的尺寸和位置
bounds:可以通過bounds來改變視圖的尺寸
center:可以通過center來改變視圖的位置
transform:可以通過transform來使視圖翻轉(zhuǎn)和縮放,平移
alpha:可以通過alpha修改視圖的透明度
backgroundColor:改變視圖的背景顏色
contentStetch:改變視圖內(nèi)容如何拉伸
1.
[UIView beginAnimations:nil context:nil];//開始動畫
[UIView setAnimationDuration:2];//持續(xù)時間
//動畫
CGAffineTransform transform = sender.transform;
sender.transform = CGAffineTransformMakeTranslation(100, 100);
sender.transform = CGAffineTransformTranslate(transform, 100, 100);
[UIView commitAnimations];//提交動畫
2.使用block
[UIView animateWithDuration:2 animations:^{
CGAffineTransform transform = sender.transform;
sender.transform = CGAffineTransformMakeTranslation(100, 100);
sender.transform = CGAffineTransformTranslate(transform, 100, 100);
}];
3.使用block
[UIView animateWithDuration:2 animations:^{
CGAffineTransform transform = sender.transform;
sender.transform = CGAffineTransformMakeTranslation(100, 100);
sender.transform = CGAffineTransformTranslate(transform, 100, 100);
} completion:^(BOOL finished) {
//動畫完成后調(diào)用的代碼段
}];
動畫常用設(shè)置
[UIView setAnimationDuration:2];動畫持續(xù)時間
[UIView setAnimationRepeatCount:1];動畫重復次數(shù)
UIViewController負責創(chuàng)建其管理的視圖及在低內(nèi)存的時候?qū)⑺麄儚膬?nèi)存中移除。還為標準的系統(tǒng)行為進行響應。
UIViewController負責管理所有UIView的層次結(jié)構(gòu),并響應設(shè)備的方向變化。
-
UIView的setNeedsDisplay和setNeedsLayout方法
- 1、在Mac OS中NSWindow的父類是NSResponder,而在iOS 中UIWindow 的父類是UIVIew。程序一般只有一個窗口但是會又很多視圖。
- 2、UIView的作用:描畫和動畫,視圖負責對其所屬的矩形區(qū)域描畫、布局和子視圖管理、事件處理、可以接收觸摸事件、事件信息的載體、等等。
- 3、UIViewController 負責創(chuàng)建其管理的視圖及在低內(nèi)存的時候?qū)⑺麄儚膬?nèi)存中移除。還為標準的系統(tǒng)行為進行響應。
- 4、layOutSubViews 可以在自己定制的視圖中重載這個方法,用來調(diào)整子視圖的尺寸和位置。
- 5、UIView的setNeedsDisplay和setNeedsLayout方法
- 首先兩個方法都是異步執(zhí)行的。而setNeedsDisplay會調(diào)用自動調(diào)用drawRect方法,這樣可以拿到UIGraphicsGetCurrentContext,就可以畫畫了。
- 而setNeedsLayout會默認調(diào)用layoutSubViews,就可以處理子視圖中的一些數(shù)據(jù)。
- 綜上所述:setNeedsDisplay方便繪圖,而layoutSubViews方便出來數(shù)據(jù)
- setNeedDisplay告知視圖它發(fā)生了改變,需要重新繪制自身,就相當于刷新界面.
- layoutSubviews在以下情況下會被調(diào)用:
- 1、init初始化不會觸發(fā)layoutSubviews。
- 2、addSubview會觸發(fā)layoutSubviews。
- 3、設(shè)置view的Frame會觸發(fā)layoutSubviews,當然前提是frame的值設(shè)置前后發(fā)生了變化。
- 4、滾動一個UIScrollView會觸發(fā)layoutSubviews。
- 5、旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件。
- 6、改變一個UIView大小的時候也會觸發(fā)父UIView上的layoutSubviews事件。
- 7、直接調(diào)用setLayoutSubviews。
- drawRect在以下情況下會被調(diào)用:
- 1、如果在UIView初始化時沒有設(shè)置rect大小,將直接導致drawRect不被自動調(diào)用。drawRect調(diào)用是在Controller->loadView, Controller->viewDidLoad 兩方法之后掉用的.所以不用擔心在控制器中,這些View的drawRect就開始畫了.這樣可以在控制器中設(shè)置一些值給View(如果這些View draw的時候需要用到某些變量值).
- 2、該方法在調(diào)用sizeToFit后被調(diào)用,所以可以先調(diào)用sizeToFit計算出size。然后系統(tǒng)自動調(diào)用drawRect:方法。
- 3、通過設(shè)置contentMode屬性值為UIViewContentModeRedraw。那么將在每次設(shè)置或更改frame的時候自動調(diào)用drawRect:。
- 4、直接調(diào)用setNeedsDisplay,或者setNeedsDisplayInRect:觸發(fā)drawRect:,但是有個前提條件是rect不能為0。
以上1,2推薦;而3,4不提倡
- drawRect方法使用注意點
- 1、若使用UIView繪圖,只能在drawRect:方法中獲取相應的contextRef并繪圖。如果在其他方法中獲取將獲取到一個 invalidate的ref并且不能用于畫圖。drawRect:方法不能手動顯示調(diào)用,必須通過調(diào)用setNeedsDisplay 或者 setNeedsDisplayInRect,讓系統(tǒng)自動調(diào)該方法。
- 2、若使用calayer繪圖,只能在drawInContext: 中(類似于drawRect)繪制,或者在delegate中的相應方法繪制。同樣也是調(diào)用setNeedDisplay等間接調(diào)用以上方法
- 3、若要實時畫圖,不能使用gestureRecognizer,只能使用touchbegan等方法來掉用setNeedsDisplay實時刷新屏幕
- layoutSubviews在以下情況下會被調(diào)用:
initWithFram:(CGRect)frame方法用來初始化一個UIView,傳入CGRect當參數(shù)
UIRespnder
- UIResponder 是 UIView 的父類。responder 能夠處理觸摸、手勢、遠程控制等事件。
- 之所以它是一個單獨的類而沒有合并到 UIView 中,是因為 UIResponder 有更多的子類,最明顯的就是 UIApplication 和 UIViewController。
- 通過重寫 UIResponder的方法,可以決定一個類是否可以成為第一響應者 (first responder),例如當前輸入焦點元素。
- 當 touches (觸摸) 或 motion (指一系列運動傳感器) 等交互行為發(fā)生時,它們被發(fā)送給第一響應者 (通常是一個視圖)。
- 如果第一響應者沒有處理,則該行為沿著響應鏈到達視圖控制器,如果行為仍然沒有被處理,則繼續(xù)傳遞給應用。
- 如果想監(jiān)測晃動手勢,可以根據(jù)需要在這3層中的任意位置處理。
- UIResponder 還允許自定義輸入方法,從 inputAccessoryView 向鍵盤添加輔助視圖到使用 inputView 提供一個完全自定義的鍵盤。