UIView的基本使用

注:参照转载https://www.jianshu.com/p/188b81450673
https://www.csdn.net/article/2015-07-07/2825139-ios-uiview-animation-3
关于UIResponder的事件处理和传递机制参见以下两篇博文:
http://yishuiliunian.gitbooks.io/implementate-tableview-to-understand-ios/content/uikit/1-1-2.html
https://link.jianshu.com?t=http://blog.csdn.net/chun799/article/details/8223612

一、UIView简介

1.UIView功能及视图层次

UIView的功能:管理矩形区域里的内容、处理矩形区域中的事件、子视图的管理、动画的实现。

UIView的视图层次

视图层次.png

2.UIView生命周期

UIView初始化方法

-(instancetype)initWithFrame:(CGRect)frame通过frame初始化UIView,也是官方推荐初始化方法。

-(nullable instancetype)initWithCoder:(NSCoder*)aDecoder如果使用NIB文件,使用此方法初始化。

UIView生命周期
loadView或nib文件来加载view到内存 -> viewDidLoad函数进一步初始化这些view -> 内存不足时, 调用viewDidUnload函数释放views -> 当需要使用view时又回到第一步

loadView:
viewController 会在view的property被请求并且当前view值为nil时调用这个函数。如果你手动创建view, 你应该重载这个函数,且不要在重载的时候调用[super loadView]。

viewDidload:

开发者可以进一步的初始化其views。viewDidLoad通常负责的是view及其子view被加载进内存之后的数据初始化的工作,即视图的数据部分的初始化

viewDidUnLoad:

viewDidLoad的对立函数,在程序内存欠缺时,这个函数被controller调用,来释放他的view以及view相关的对象。由于controller通常保存着view以及相关的object的引用,所以你必须使用这个函数来放弃这些对象的所有权以便内存回收,但不要释放那些难以重建的数据

viewWillAppear:视图即将可见时被调用。

viewDidAppear:视图已完全过渡到屏幕上时被调用

viewWillDisappear:视图将退出时别调用,覆盖或以其他方式隐藏。

viewDidDisappear:视图退出后被调用,覆盖或以其他方式隐藏。调用时机会在当前页面消失后,下个页面viewWillAppear前。

didReceiveMemoryWarning:当程序内存过度时,系统会调用该方法

3.UIView常用属性

三个结构体

struct CGPoint{CGFloat x;CGFloat y;};

struct CGSize{CGFloat width;CGFloat height;};

struct CGRect{CGPoint origin;CGSize size;};

基本属性

frame是CGRect frame的origin是相对于父视图的左上角原点(0,0)的位置,改变视图的frame会改变center

center是CGPoint指的就是整个视图的中心点,改变视图的center也会改变frame

bounds是CGRect是告诉子视图本视图的原点位置(通俗的说就是,子视图的frame的origin与父视图的bounds的origin的差,就是子视图相对于父视图左上角的位置,如果结果为负,则子视图在父视图外)

transform是UIView通过设置该属性,我们可以实现调整该view在其superView中的大小和位置,具体来说,Transform(变化矩阵)是一种3×3的矩阵,通过这个矩阵我们可以对一个坐标系统进行缩放,平移,旋转以及这两者的任意组着操作。而且矩阵的操作不具备交换律,即矩阵的操作的顺序不同会导致不同的结果。
常用的三种实现选中的方式:
view.transform=CGAffineTransformScale(view.transform, 0.5, 0.5); // 实现的是放大和缩小 view.transform=CGAffineTransformRotate(view.transform, 0.2); //实现的是旋转 view.transform=CGAffineTransformTranslate(view.transform, 20, 20); //实现的是平移

常见属性

alpha:UIView中alpha是一个浮点值,取值范围0~1.0,表示从完全透明到完全不透明。

hidden:该属性为BOOL值,用来表示UIView是否隐藏,默认值是NO。

opaque:表示当前UIView是否不透明,该属性为BOOL值,UIView的默认值是YES,但UIButton等子类的默认值都是NO。事实上它却决定不了当前UIView是不是不透明,比如你将opaque设为NO,该UIView照样是可见的。

clipsToBounds:决定了子视图的显示范围。具体的说,就是当取值为YES时,剪裁超出父视图范围的子视图部分;当取值为NO时,不剪裁子视图。默认值为NO。

4.管理View的层次结构

1、superview

接收者的父类。

2、subviews

接收者的子类。

3、window

UIWindow对象是所有UIView的根视图,管理和协调的应用程序的显示、分发事件给View。UIWindow类是UIView的子类,可以看作是特殊的UIView。一般应用程序只有一个UIWindow对象,即使有多个UIWindow对象,也只有一个UIWindow可以接受到用户的触屏事件。

4、- addSubview:

添加一个子视图到接收者并让它在最上面显示出来。

5、- bringSubviewToFront:

将某个子视图调整到最上边。
-(void)bringSubviewToFront:(UIView*)view

6、- sendSubviewToBack:

将某个子视图调整到最下边。
-(void)sendSubviewToBack:(UIView*)view

7、- removeFromSuperview

将子视图从父视图中移除掉。

8、- insertSubview:atIndex:

在特定的位置,插入一个子视图。
view:被插入的子视图。
index:被插入的位置下标,位置下标从0开始;下标不能大于子视图的总数。
-(void)insertSubview:(UIView*)view atIndex:(NSInteger)index

9、- insertSubview:aboveSubview:

插入一个View到指定View的上层。
-(void)insertSubview:(UIView)view aboveSubview:(UIView)siblingSubView

10、- insertSubview:belowSubview:

插入一个View到指定View的下层。
-(void)insertSubview:(UIView)view belowSubview:(UIView)siblingSubView

11、-exchangeSubviewAtIndex:withSubviewAtIndex:

根据下标交换两个层的位置。
(void)exchangeSubviewAtIndex:
(NSInteger)indexwithSubviewAtIndex:(NSInteger)index

12、- isDescendantOfView:

返回一个布尔值指出接收者是否是给定视图的子视图或者指向那个视图。用来测试子视图在视图层次中的关系,返回值如果接收者是视图的子视图或者视图就是接收者就返回YES;否则就是NO;

5.UIView Animation

1.frame,bounds,center//改变View的frame属性
2.alpha //改变透明度
3.backgroundColor //改变背景颜色

-(void)doChangeFrame
 { 
 [UIView animateWithDuration:2.0 animations:^(void){ 
    smallImage.frame = CGRectMake(150, 80, 30, 30);
 
 } completion:^(BOOL finished) {
 
     smallImage.alpha = 0;
 
 }];
 
}

4.contentStretch //拉伸变化
5.transform //仿射变换,其中又包括Rotate,Invert,Translate,Scale(旋转,反转,位移,缩放)

 -(void)doRotate//旋转
 
 {
 
 CGAffineTransform transform=  CGAffineTransformMakeRotation(M_PI/4);
 
 [UIView beginAnimations:nil context:nil];
 
 bigImage.transform = transform;
 
 [UIView commitAnimations];
 
 }

 -(void)doInvert//反转
 
 {
 
 BOOL isSingle = seg.selectedSegmentIndex;
 
 //如果单次 直接翻转到原始状态 如果连续 在以前基础上再次进行反转
 
CGAffineTransform transform = isSingle?CGAffineTransformInvert(bigImage.transform):CGAffineTransformIdentity;

 [UIView beginAnimations:nil context:nil];
 
 bigImage.transform = transform;
 
 [UIView commitAnimations];
 
 }

 -(void)doTranslate//位移
 
 {
 
 BOOL isSingle = seg.selectedSegmentIndex;
 
 //如果单次 只改变一次 如果连续 在以前基础上再次进行移位
 CGAffineTransform transform = isSingle?CGAffineTransformMakeTranslation(10, 10):CGAffineTransformTranslate(bigImage.transform, 10, 10); 
 [UIView animateWithDuration:1 animations:^{  bigImage.transform = transform;  
}]; 
 }

 -(void)doScale//缩放
 
 {
 
 BOOL isSingle = seg.selectedSegmentIndex;
 
 //如果单次 只改变一次 如果连续 在以前基础上再次进行缩放
 
 CGAffineTransform transform = isSingle?CGAffineTransformMakeScale(1.0, 1.1):CGAffineTransformScale(bigImage.transform, 1.0, 1.1);
 
 [UIView beginAnimations:nil context:nil];
 
 bigImage.transform = transform;
 
 [UIView commitAnimations];
 
 }

6.CALayer 和 UIView 的区别和联系

UIView之所以能显示在屏幕上,完全是因为它内部的一个图层,在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层

@property(nonatomic,readonly,retain) CALayer *layer;

当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的图层上,绘图完毕后,系统会将图层拷贝到屏幕上,于是就完成了UIView的显示

换句话说,UIView本身不具备显示的功能,拥有显示功能的是它内部的图层。

a.UIView可以响应事件,Layer不可以

UIKit使用UIResponder作为响应对象,来响应系统传递过来的事件并进行处理。UIApplication、UIViewController、UIView、和所有从UIView派生出来的UIKit类(包括UIWindow)都直接或间接地继承自UIResponder类。

在 UIResponder中定义了处理各种事件和事件传递的接口, 而 CALayer直接继承 NSObject,并没有相应的处理事件的接口。

下面四个方法分别处理触摸开始事件,触摸移动事件,触摸终止事件,以及触摸跟踪取消事件。

– touchesBegan:withEvent:

– touchesMoved:withEvent:

– touchesEnded:withEvent:

– touchesCancelled:withEvent:

b.CALayer的创建

Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的,而一个 View 的 frame 只是简单的返回 Layer的 frame,同样 View 的 center和 bounds 也是返回 Layer 的一些属性。

CALayer的创建时机是在[view initWithFrame] 的时候调用私有方法【UIView _createLayerWithFrame】去创建的。

c.UIView主要是对显示内容的管理而 CALayer 主要侧重显示内容的绘制。

UIView 是 CALayer 的CALayerDelegate,在代理方法内部[UIView(CALayerDelegate) drawLayer:inContext]调用 UIView 的 DrawRect方法,从而绘制出了 UIView 的内容.

d.CALayer重用视觉效果

调整图层的大小和位置

调整图层的背景颜色

修改图层的内容 (一个图片,或者是用CoreGraphics绘制的东西)

图层是否圆角

添加黑色投影

添加描边的边框

二、UIWindow简介

在iOS App中,UIWindow是最顶层的界面内容,我们使用UIWindow和UIView来呈现界面。UIWindow并不包含任何默认的内容,但是它被当作UIView的容器,用于放置应用中所有的UIView。

从继承关系来看,UIWindow继承自UIView,所以UIWindow除了具有UIView的所有功能之外,还增加了一些特有的属性和方法,而我们最常用的方法,就是在App刚启动时,调用UIWindow的makeKeyAndVisible方法,代码如下:

  • (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary)launchOptions {

self.window= [[UIWindowalloc] initWithFrame:[[UIScreen mainScreen] bounds]];

HomeNavigationController *viewController = [HomeNavigationController sharedNavigationController];

self.window.rootViewController= viewController;

[self.windowmakeKeyAndVisible];

returnYES;

}

总的来看,UIWindow的主要作用有:

1.作为UIView的最顶层容器,包含应用显示所有的UIView;

2.传递触摸消息和键盘事件给UIView;

UIWindow添加UIView

通常有两种方式向UIWindow中添加UIView:

1.通过调用addSubView方法,因为UIWindow是UIView的子类,所以它可以使用UIView的addSubView方法给自己增加子UIView,从而承担容器的作用;

2.通过设置其特有的rootViewController属性。设置该属性后,UIWindow会自动将view controller的view添加到当前window中,同时负责维护view controller和view的生命周期。上述在application:didFinishLaunchingWithOptions:中使用的就是这种办法;

UIWindow的使用

通常在一个程序中只会有一个UIWindow,但有些时候我们调用系统的控件(例如UIAlertView)时,iOS系统为了保证UIAlertView在所有的界面之上,它会临时创建一个新的UIWindow,通过将其UIWindowLevel设置更高,让UIAlertView盖在所有其他UI之上。

UIWindow的层级由一个UIWindowLevel类型属性windowLevel,该属性指示了UIWindow的层级,windowLevel有三种可取值:

UIKIT_EXTERNconstUIWindowLevel UIWindowLevelNormal;

UIKIT_EXTERNconstUIWindowLevel UIWindowLevelAlert;

UIKIT_EXTERNconstUIWindowLevel UIWindowLevelStatusBar;

从中能够看出,默认程序的UIWindow的层级是UIWindowLevelNormal,当系统需要覆盖在其上覆盖UIAlertView时,就会创建一个层级是UIWindowLevelAlert的UIWindow,因为其windowLevel值更高,所以就覆盖在上面了

有些时候,我们也希望在应用开发中,将某些界面覆盖在所有界面的最上层。这个时候,我们就可以手工创建一个新的UIWindow。需要注意的是,和创建UIView不同,UIWindow一旦被创建,它就自动地被添加到整个界面上了(当然,其windowLevel要足够高)。

还有一点需要注意的是,如果我们创建的UIWindow需要处理键盘事件,那就需要合理地将其设置为keyWindow。keyWindow是被系统设计用来接收键盘和其他非触摸事件的UIWindow。我们可以通过makeKeyWindow和resignKeyWindow方法设置UIWindow实例的keyWindow与否。

唐巧在《iOS开发进阶》里的描述,支付宝钱包等App的密码保护页面是基于UIWindow实现的,当用户从应用的任何界面按Home键退出,过一段时间再从后台切换回来时,显示一个密码输入界面。只有用户输入了正确的密码,才能进入退出前的界面。因为这个密码输入界面可能从任何应用界面弹出,并且需要盖住所有界面的最上层,所以很合适做一个UIWindow来实现。

UIWindow的获取

1.通过[UIApplication sharedApplication].windows 获取在应用中打开的UIWindow列表,可以获取应用中的任何一个UIView对象,例如 当输入文字时,弹出的键盘就是UIWindow,如果需要改变键盘的样式,则可用更改当前Window。

2.通过[UIApplication sharedApplication].keyWindow获取应用程序的主窗口,用来接收键盘以及非触摸类的消息事件的UIWindow,而且程序中每个时刻只能有一个UIWindow是keyWindow。

3.通过view.window获得某个UIView所在的UIWindow

你可能感兴趣的:(UIView的基本使用)