? UIview 遵循的代理屬性

UiView的一些代理 一.<NSCoding>

我們會在以下這些場合用到NSCoding:

1. XIB/Storyboard

我們在創建一個UIView的subclass的時候,會注意到,如果我們希望在初始化這個view的時候就要做一些事情,不但要覆蓋掉initWithFrame:方法,也要覆蓋initWithCoder:方法。

如果這個view是我們用代碼創建的,那么會調用到initWithFrame:方法,但如果我們是XIB則會調用initWithCoder:這個方法。

XIB或是Storyboard在我們編寫程序的期間是XML格式的檔案,當我們編譯App的時候,XCode會將其編譯成binary格式的data,分別是NIB與storyboardc,而這些data其實就是序列化過的Objective-C View對象。

將data轉成view,這個流程正是NSCoding protocol,我們從UIView的interface中可以看到UIView實現了NSCoding protocol。

2. NSUserDefaults

在我們的App中,如果我們要儲存一些偏好設定,那么最好的選擇就是NSUserDefaults。操作NSUserDefaults和操作NSDictionary差不多,只要指定特定的key,就可以將設定值存入NSUserDefaults中。

NSUserDefaults支持NSString、NSArray、NSDictionary、NSData以及int、doubel、float等類型的數據。

但如果是我們自定義的Class,就無法存入NSUserDefaults中,我們會先通過NSCoding轉成NSData后存入,在取出的時候也要多做一次unarchive(反序列化)。

二.<UIAppearance和UIAppearanceContainer>

iOS5及其以后提供了一個比較強大的工具UIAppearance,我們通過UIAppearance設置一些UI的全局效果,這樣就可以很方便的實現UI的自定義效果又能最簡單的實現統一界面風格,它提供如下兩個方法。

+ (id)appearance

這個方法是統一全部改,比如你設置UINavBar的tintColor,你可以這樣寫:[[UINavigationBar appearance] setTintColor:myColor];

+ (id)appearanceWhenContainedIn:(Class <>)ContainerClass,...

這個方法可設置某個類的改變:例如:設置UIBarButtonItem 在UINavigationBar、UIPopoverController、UITabbar中的效果。就可以這樣寫

[[UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], [UIPopoverController class],[UITabbar class] nil] setTintColor:myPopoverNavBarColor];

請注意*使用appearance設置UI效果最好采用全局的設置,在所有界面初始化前開始設置,否則可能失效。

具體UI外觀修改如下:

1.修改導航欄背景

代碼如下:

UINavigationBar * appearance = [UINavigationBar appearance];

UIImage *navBackgroundImg =[UIImage imageNamed:@"navBg.png”];

[appearance setBackgroundImage:navBackgroundImg forBarMetrics:UIBarMetricsDefault];

2.標簽欄(UITabbar)

代碼如下:

UITabBar *appearance = [UITabBar appearance];

//設置背景圖片

[appearance setBackgroundImage:[UIImage imageNamed:@"tabbar_bg.png"]];

//門置選擇item的背景圖片

UIImage * selectionIndicatorImage =[[UIImage imageNamed:@"tabbar_slider"]resizableImageWithCapInsets:UIEdgeInsetsMake(4, 0, 0, 0)] ;

[appearance setSelectionIndicatorImage:selectionIndicatorImage];

3.分段控件(UISegmentControl)

代碼如下:

UISegmentedControl *appearance = [UISegmentedControl appearance];

//Segmenteg正常背景

[appearance setBackgroundImage:[UIImage imageNamed:@"Segmente.png"]

forState:UIControlStateNormal

barMetrics:UIBarMetricsDefault];

//Segmente選中背景

[appearance setBackgroundImage:[UIImage imageNamed:@"Segmente_a.png"]

forState:UIControlStateSelected

barMetrics:UIBarMetricsDefault];

//Segmente左右都未選中時的分割線

//BarMetrics表示navigation bar的狀態,UIBarMetricsDefault 表示portrait狀態(44pixel height),UIBarMetricsLandscapePhone 表示landscape狀態(32pixel height)

[appearance setDividerImage:[UIImage imageNamed:@"Segmente_line.png"]

forLeftSegmentState:UIControlStateNormal

rightSegmentState:UIControlStateNormal

barMetrics:UIBarMetricsDefault];

[appearance setDividerImage:[UIImage imageNamed:@"Segmente_line.png"]

forLeftSegmentState:UIControlStateSelected

rightSegmentState:UIControlStateNormal

barMetrics:UIBarMetricsDefault];

[appearance setDividerImage:[UIImage imageNamed:@"Segmente_line.png"]

forLeftSegmentState:UIControlStateNormal

rightSegmentState:UIControlStateSelected

barMetrics:UIBarMetricsDefault];

//字體

NSDictionary *textAttributes1 = @{UITextAttributeFont: [UIFont systemFontOfSize:18],

UITextAttributeTextColor: [UIColor blueColor],

UITextAttributeTextShadowColor: [UIColor whiteColor],

UITextAttributeTextShadowOffset: [NSValue valueWithCGSize:CGSizeMake(1, 1)]};

[appearance setTitleTextAttributes:textAttributes1 forState:1];

NSDictionary *textAttributes2 = @{UITextAttributeFont: [UIFont systemFontOfSize:18],

UITextAttributeTextColor: [UIColor whiteColor],

UITextAttributeTextShadowColor: [UIColor blackColor],

UITextAttributeTextShadowOffset: [NSValue valueWithCGSize:CGSizeMake(1, 1)]};

[appearance setTitleTextAttributes:textAttributes2 forState:0];

4.UIBarbutton

注意:UIBarbutton有leftBarButton,rightBarButton和backBarButton,其中backBarButton由于帶有箭頭,需要單獨設置。

barButton背景設置是ios6.0及以后的,而backbutton是ios5.0及以后的,這里要注意!

代碼如下:

//修改導航條上的UIBarButtonItem

UIBarButtonItem *appearance = [UIBarButtonItem appearanceWhenContainedIn:[UINavigationBar class], nil];

//設置導航欄的字體包括backBarButton和leftBarButton,rightBarButton的字體

NSDictionary *textAttributes = @{UITextAttributeFont: [UIFont systemFontOfSize:18],

UITextAttributeTextColor: [UIColor blueColor],

UITextAttributeTextShadowColor: [UIColor whiteColor],

UITextAttributeTextShadowOffset: [NSValue valueWithCGSize:CGSizeMake(1, 1)]};

[appearance setTitleTextAttributes:textAttributes forState:1];//forState為0時為下正常狀態,為1時為點擊狀態。

//修改leftBarButton,rightBarButton背景效果

[appearance setBackgroundImage:[UIImage imageNamed:@"navBarButton.png"]

forState:UIControlStateNormal

style:UIBarButtonItemStyleBordered

barMetrics:UIBarMetricsDefault];

[appearance setBackgroundImage:[UIImage imageNamed:@"navBarButton_a.png"]

forState:UIControlStateHighlighted

style:UIBarButtonItemStyleBordered

barMetrics:UIBarMetricsDefault];

//backBarButton需要單獨設置背景效果。只能在ios6.0以后才能用

[appearance setBackButtonBackgroundImage:[UIImage imageNamed:@"nav_bg.png"]

forState:0

barMetrics:UIBarMetricsDefault];

[appearance setBackButtonBackgroundImage:[UIImage imageNamed:@"work.png"]

forState:1

barMetrics:UIBarMetricsDefault];

[appearance setBackButtonTitlePositionAdjustment:UIOffsetMake(2, -1)

forBarMetrics:UIBarMetricsDefault];

5.工具欄(UIToolbar)

UIToolbar *appearance = [UIToolbar appearance];

//樣式和背景二選一即可,看需求了

//樣式(黑色半透明,不透明等)設置

[appearance setBarStyle:UIBarStyleBlackTranslucent];

//背景設置

[appearance setBackgroundImage:[UIImage imageNamed:@"toolbarBg.png"]

forToolbarPosition:UIToolbarPositionAny

barMetrics:UIBarMetricsDefault];

三.<DynamicItem>

所有的UIView類都是一個DynamicItem對象,都可以實現UIDynamic動畫。UIDynamic,隸屬于UIKit框架,可以認為是一種物理引擎,能模擬和仿真現實生活中的物理現象重力、彈性碰撞等現象。

UIDynamic使用步驟

創建一個物理仿真器(順便設置仿真范圍)

創建相應的物理仿真行為(順便添加物理仿真元素)

將物理仿真行為添加到物理仿真器中,開始仿真。

任何遵守了UIDynamicItem協議的對象都可以作為物理仿真元素。(UIView)

UIView默認已經遵守了UIDynamicItem協議,因此任何UI控件都能做物理仿真

UICollectionViewLayoutAttributes類默認也遵守UIDynamicItem協議。

物理仿真行為UIDynamic提供了以下幾種物理仿真行為UIGravityBehavior:

重力行為UICollisionBehavior:

碰撞行為UISnapBehavior:

捕捉行為UIPushBehavior:

推動行為UIAttachmentBehavior:

附著行為UIDynamicItemBehavior:

動力元素行為物理仿真器它可以讓物理仿真元素執行物理仿真行為,它是UIDynamicAnimator類型的對象。

UIDynamicAnimator的初始化- (instancetype)initWithReferenceView:(UIView *)view;view參數:是一個參照視圖,表示物理仿真的范圍UIDynamicAnimator的常見方法

//添加1個物理仿真行為- (void)addBehavior:(UIDynamicBehavior *)behavior;//移除1個物理仿真行為- (void)removeBehavior:(UIDynamicBehavior *)behavior;

//移除之前添加過的所有物理仿真行為- (void)removeAllBehaviors;UIDynamicAnimator的常見屬性//參照視圖@property (nonatomic, readonly) UIView* referenceView;

//添加到物理仿真器中的所有物理仿真行為@property (nonatomic, readonly, copy) NSArray* behaviors;

//是否正在進行物理仿真@property (nonatomic, readonly, getter = isRunning) BOOL running;

//代理對象(能監聽物理仿真器的仿真過程,比如開始和結束)@property (nonatomic, assign) iddelegate;

四.<UITraitEnvironment>

為了表征 Size Classes,Apple 在 iOS 8 中引入了一個新的類--UITraitCollection。這個類封裝了像水平和豎直方向的 Size Class 等信息。iOS 8 的 UIKit 中大多數 UI 的基礎類 (包括 UIScreen,UIWindow,UIViewController 和 UIView) 都實現了 UITraitEnvironment 這個接口,通過其中的 traitCollection 這個屬性,我們可以拿到對應的 UITraitCollection 對象,從而得知當前的 Size Class,并進一步確定界面的布局。

和 UIKit 中的響應者鏈正好相反,traitCollection 將會在 view hierarchy 中自上而下地進行傳遞。對于沒有指定 traitCollection 的 UI 部件,將使用其父節點的 traitCollection。這在布局包含 childViewController 的界面的時候會相當有用。在 UITraitEnvironment 這個接口中另一個非常有用的是 -traitCollectionDidChange:。在 traitCollection 發生變化時,這個方法將被調用。在實際操作時,我們往往會在 ViewController 中重寫 -traitCollectionDidChange: 或者 -willTransitionToTraitCollection:withTransitionCoordinator: 方法 (對于 ViewController 來說的話,后者也許是更好的選擇,因為提供了轉場上下文方便進行動畫;但是對于普通的 View 來說就只有前面一個方法了),然后在其中對當前的 traitCollection 進行判斷,并進行重新布局以及動畫。

五.<UICoordinateSpace protocol>

iOS 8之前,window和screen的坐標是不變的。它們不會進行旋轉,而是一直處于豎屏時的坐標體系。我們是在View Controller旋轉方法中做對應的處理。

iOS8之后,像上文描述的那樣,window和screen的坐標會隨著app旋轉而改變。也不總是這樣的情況,因為View Controller仍然決定了App在當前視圖下支持哪幾個方向。 在某些時候,我們需要一些修正之后的frame(比如需要存儲touch事件在屏幕上的坐標),這個時候新的UICoordinateSpace就登場了。

UICoordinateSpace協議的接口如上,使用這些接口我們可以從當前視圖的坐標轉化到在screen的坐標體系當中,像這樣:[myView convertPoint:point toCoordinateSpace:myView.window.screen.fixedCoordinateSpace];這里提到了fixedCoordinateSpace,在iOS 8上UIScreen提供了兩個新的屬性,如下:@property (readonly) idcoordinateSpace NS_AVAILABLE_IOS(8_0);@property (readonly) idfixedCoordinateSpace NS_AVAILABLE_IOS(8_0);

coordinateSpace值的是當前screen旋轉之后的坐標體系,fixedCoordinateSpace指的是修正之后的坐標體系。我們同樣可以把screen的坐標轉換到當前視圖的坐標體系,如下:

[myView.window.screen.fixedCoordinateSpace convertPoint:point? ? ? toCoordinateSpace:myView];

舉個例子來說,在iPhone 5的屏幕大小上(320 * 568),myView在豎屏方向的frame是CGRectMake(50, 50, 200, 200),myView的Super View是window。有如下輸出結果:

CGPoint point = [myView convertPoint:CGPointMake(0, 0) toCoordinateSpace:[UIScreen mainScreen].fixedCoordinateSpace];

NSLog(@"fixedCoordinateSpace %@", NSStringFromCGPoint(point)); // {50, 50}

point = [myView convertPoint:CGPointMake(0, 0) toCoordinateSpace:[UIScreen mainScreen].coordinateSpace];

NSLog(@"coordinateSpace %@", NSStringFromCGPoint(point)); // {50, 50}

此時我們把設備順時針旋轉90度,在這兩種不同的坐標體系下分別輸出的結果是:

NSLog(@"fixedCoordinateSpace %@", NSStringFromCGPoint(point)); // {50, 518}

NSLog(@"coordinateSpace %@", NSStringFromCGPoint(point)); // {50, 50}

六.<UIFocusItem>

該協議用于描述第三方類,允許在一個項目中申報其參與焦點系統的能力。

UIView的對象符合UIFocusItem協議能夠參與焦點系統;此外,只能集中UIFocusItem對象。

即使一個對象符合UIFocusItem不是目前focusable,它可能仍然關注系統產生影響。例如,項目設置成不可定焦,但這完全掩蓋其他物品,可能防止focusable其他物品,因為他們對用戶是不可見的。另外,因為UIFocusItem符合UIFocusEnvironment,仍可能影響項目設置成不可定焦的關注行為他們包含的商品,或者對焦點更新。是在iOS10以后新增加的類目。

七.<CALayerDelegate>

CALayer的基本操作.

CALayer簡介:

CALayer我們又稱為層,在每個UIView內部都有一個layer的屬性,UIView之所以能夠顯示,就是因為它里面有layer層,才具有顯示的功能,我們通過操作CALayer對象,可以很方便地調整UIView的一些外觀屬性,例如可以給UIView設置陰影,圓角,邊框等等...

操作layer改變UIView外觀.

2.1 設置陰影

//默認圖層是有陰影的, 只不過是透明的。1為不透明,0為透明_RedView.layer.shadowOpacity = 1;//設置陰影的偏移量self.imageV.layer.shadowOffset = CGSizeMake(-30, -10);//設置陰影的模糊程度self.imageV.layer.shadowRadius = 10;//設置陰影的圓角_RedView.layer.shadowRadius =10;//設置陰影的顏色,把UIKit轉換成CoreGraphics框架,用.CG開頭_RedView.layer.shadowColor = [UIColor blueColor].CGColor;

2.2.設置邊框

設置圖層邊框,在圖層中使用CoreGraphics的CGColorRef//設置邊框的顏色_RedView.layer.borderColor = [UIColor whiteColor].CGColor;//設置邊框的寬度_RedView.layer.borderWidth = 2;

2.3.設置圓角

圖層的圓角半徑,圓角半徑為寬度的一半, 就是一個圓_RedView.layer.cornerRadius = 50;

操作layer改變UIImageView的外觀.

3.1 設置陰影

//UIView本身就自帶陰影效果,它是透明._imageView.layer.shadowOpacity = 1;//設置陰影的偏移量_imageView.layer.shadowOffset = CGSizeMake(-30, -10);//設置陰影的模糊程度_imageView.layer.shadowRadius = 10;//設置陰影的顏色_imageView.layer.shadowColor = [UIColor blueColor].CGColor;

3.2 設置圖形邊框

//設置邊框寬度_imageView.layer.borderWidth = 2;//設置邊框顏色_imageView.layer.borderColor = [UIColor whiteColor].CGColor;

3.3 設置圖片的圓角半徑

//我們設置的所有layer的屬性只作用在根層上,根層設置為圓形后,其上面的圖片并不會改變,因此需要裁剪。_imageView.layer.cornerRadius = 50;//裁剪,超出裁剪區域的部分全部裁剪掉_imageView.layer.masksToBounds = YES;

注意:UIImageView當中Image并不是直接添加在根層上面的.而是添加在layer當中的contents層里.我們設置層的所有屬性它只作用在根層上面.對contents里面的東西并不起作用.所以我們看不到圖片有圓角的效果.想要讓圖片有圓角的效果.可以把masksToBounds這個屬性設為YES.把就會把超過根層以外的東西都給裁剪掉.

layer的 CATransform3D屬性.

只有旋轉的時候才可以看出3D的效果.

//x,y,z 分別代表x,y,z軸. //旋轉CATransform3DMakeRotation(M_PI, 1, 0, 0);//平移CATransform3DMakeTranslation(x,y,z)//縮放CATransform3DMakeScale(x,y,z);//可以通過KVC的方式進行設置屬性.//但是CATransform3DMakeRotation的值是一個結構體, 所以要把結構轉成對象.NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI, 1, 0, 0)];[_imageView.layer setValue:value forKeyPath:@"transform.scale"];

什么時候用KVC?當需要做一些快速縮放,平移,二維的旋轉時用KVC.比如: [_imageView.layer setValue:@0.5 forKeyPath:@"transform.scale"];快速的進行縮放.后面forKeyPath屬性值不是亂寫的.蘋果文檔當中給了相關的屬性.

forKeyPath屬性值

自定義CALayer.

2.1 如何自定義Layer.

自定義CALayer的方式創建UIView的方式非常相似.

CALayer *layer = [CALayer layer];layer.frame = CGRectMake(50, 50, 100, 100);layer.backgroundColor = [UIColor redColor].CGColor;[self.view.layer addSublayer:layer];給layer設置圖片.layer.contents = (id)[UIImage imageNamed:@"icon"].CGImage;

2.2 關于CALayer的疑惑?

為什么要使用CGImageRef、CGColorRef?

CALayer定義在QuartzCore框架中.CGImageRef、CGColorRef兩種數據類型定義在CoreGraphics框架中.UIColor、UIImage定義在UIKit框架中.QuartzCore框架和CoreGraphics框架是可以跨平臺使用的,在iOS和Mac OSX上都能使用.但是UIKit框架只能在iOS中使用.所以為了保證可移植性,QuartzCore不能使用UIImage、UIColor,只能使用CGImageRef、CGColorRef.

UIView和CALayer都能夠顯示東西,該怎樣選擇?

對比CALayer,UIView多了一個事件處理的功能。也就是說,CALayer不能處理用戶的觸摸事件,而UIView可以,但是CALayer的性能會高一些,因為它少了事件處理的功能,更加輕量級如果顯示出來的東西需要跟用戶進行交互的話,用UIView;如果不需要跟用戶進行交互,用UIView或者CALayer都可以我們平常開發中一般用UIView.

CALayer的兩個重要屬性position和anchorPoint

position和anchorPoint是CAlayer的兩個屬性.我們以前修改一個控件的位置都是能過Frame的方式進行修改.現在利用CALayer的position和anchorPoint屬性也能夠修改控件的位置.

這兩個屬性是配合使用的.position:它是用來設置當前的layer在父控件當中的位置的.所以它的坐標原點.以父控件的左上角為(0.0)點.anchorPoint:它是決點CALayer身上哪一個點會在position屬性所指的位置anchorPoint是以當前的layer左上角為原點(0.0),它的取值范圍是0~1,默認位置在中間也就是(0.5,0.5).anchorPoint又稱錨點.就是把錨點定到position所指的位置.兩者結合使用.想要修改某個控件的位置,我們可以設置它的position點.設置完畢后.layer身上的anchorPoint會自動定到position所在的位置.

position和anchorpint圖示

隱式動畫.

4.1 什么是隱式動畫?

了解什么是隱式動畫前,要先了解什么是根層和非根層.根層:UIView內部自動關聯著的那個layer我們稱它是根層.非根層:自己手動創建的層,稱為非根層.

隱式動畫就是當對非根層的部分屬性進行修改時, 它會自動的產生一些動畫的效果.我們稱這個默認產生的動畫為隱式動畫.這些屬性稱為Animatable Properties(可動畫屬性)。也就是 手動創建的CALayer對象,都存在著隱式動畫

列舉常見的Animatable Properties:

bounds:CALayer的寬度和高度,修改時產生縮放動畫。

backgroundColor:背景顏色,修改時產生背景顏色漸變動畫效果。

position:CALayer的位置,修改時產生平移動畫

例:

如何取消隱式動畫?首先要了解動畫底層是怎么做的.動畫的底層是包裝成一個事務來進行的.什么是事務?很多操作綁定在一起,當這些操作執行完畢后,才去執行下一個操作.

因此我們自己開啟事務,并在事物中設置沒有動畫就會隱藏動畫了

//開啟事務[CATransaction begin];//設置事務沒有動畫[CATransaction setDisableActions:YES];//設置動畫執行的時長[CATransaction setAnimationDuration:2];//這其中修改屬性就沒有動畫了//提交事務[CATransaction commit];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,147評論 5 13
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,573評論 6 30
  • 在iOS實際開發中常用的動畫無非是以下四種:UIView動畫,核心動畫,幀動畫,自定義轉場動畫。 1.UIView...
    請叫我周小帥閱讀 3,169評論 1 23
  • 一、定時任務 方法1:performSelector 方法2:GCD 方法3:NSTimer NSTimer「定時...
    _涼風_閱讀 1,311評論 2 8