UIView为屏幕上的矩形区域管理内容的对象。视图是应用程序用户界面的基本构建块,UIView类定义了全部视图通用的行为。视图对象呈现其边界矩形内的内容,并处理与该内容的任何交互。ios
UIView类是一个具体的类,您能够实例化它并使用它来显示固定的背景色。您还能够将其子类化以绘制更复杂的内容。要显示应用程序中常见的标签、图像、按钮和其余界面元素,请使用UIKit框架提供的视图子类,而不要试图定义本身的视图子类。编程
由于视图对象是应用程序与用户交互的主要方式,因此它们有许多职责。如下是一些:数组
3.事件处理缓存
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;markdown
函数描述 : 使用指定的框架矩形初始化并返回新分配的视图对象。新视图对象必须插入到窗口的视图层次结构中才能使用。若是以编程方式建立视图对象,则此方法是UIView类的指定初始值设定项。子类能够重写此方法以执行任何自定义初始化,但必须在其实现开始时调用super。框架
若是使用Interface Builder设计接口,则在随后从nib文件加载视图对象时不调用此方法。nib文件中的对象被从新构造,而后使用它们的initWithCoder:方法进行初始化,该方法修改视图的属性以匹配存储在nib文件中的属性。ide
参数 :函数
frame : 视图的边框矩形,以点为单位。框架的原点相对于要在其中添加它的超视图。此方法使用框架矩形相应地设置中心和边界属性。布局
返回值 : 初始化的视图对象。性能
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
复制代码
@property(nonatomic) CGRect frame;
属性描述 : 框架矩形,用于描述视图在其父视图坐标系中的位置和大小。在布局操做期间使用此矩形可设置视图的大小和位置。设置此属性会更改center属性指定的点,并相应地更改边界矩形中的大小。frame的坐标老是以点表示。对该属性的更改能够被动画化。
若是transform属性不是identity转换,则该属性的值未定义,所以应该忽略。改变frame会自动从新显示视图,而无需调用它的drawRect:方法。若是你想让UIKit在frame改变时调用drawRect:方法,将contentMode属性设置为UIViewContentModeRedraw。可是,若是transform属性包含非标识转换,那么frame属性的值是未定义的,不该该被修改。在这种状况下,使用center属性从新定位视图,并使用bounds属性调整大小。
@property(nonatomic) CGRect frame;
复制代码
@property(nonatomic) CGRect bounds;
函数描述 : 边界矩形,它在本身的坐标系统中描述视图的位置和大小。默认边界原点为(0,0),大小与frame属性中矩形的大小相同。更改此矩形的大小部分会使视图相对于其中心点增大或缩小。更改大小还会更改frame属性中矩形的大小以进行匹配。bounds的坐标始终以点指定。对该属性的更改能够被动画化。
改变bounds会自动从新显示视图,而无需调用它的drawRect:方法。若是你想让UIKit调用drawRect:方法,将contentMode属性设置为UIViewContentModeRedraw。
@property(nonatomic) CGRect bounds;
复制代码
@property(nonatomic) CGPoint center;
函数描述 : 视图frame的中心点。中心点在其父视图的坐标系中以点指定。设置此属性将相应地更新frame属性中矩形的原点。若是要更改视图的位置,请使用此属性,而不是frame属性。中心点始终有效,即便在将缩放或旋转因子应用于视图的变换时也是如此。对此属性的更改能够设置动画。
@property(nonatomic) CGPoint center;
复制代码
@property(nonatomic) CGAffineTransform transform;
属性描述 : 指定应用于视图的相对于其边界中心的转换。使用这个属性在父视图的坐标系统内缩放或旋转视图的frame。(要改变视图的位置,请修改center属性。)此属性的默认值是CGAffineTransformIdentity。对该属性的更改能够被动画化。
相对于视图的锚点发生转换。默认状况下,定位点等于frame的中心点。要更改锚点,请修改视图的底层CALayer对象的锚点属性。
在ios8.0及之后版本中,transform属性不会影响自动布局。自动布局计算一个视图的对齐矩形基于它的未转换的框架。
当此属性的值不是identity转换时,frame属性中的值是未定义的,应该忽略。
@property(nonatomic) CGAffineTransform transform;
复制代码
@property(nonatomic) CGFloat contentScaleFactor API_AVAILABLE(ios(4.0));
属性描述 :应用于视图的比例因子。比例因子决定如何将视图中的内容从逻辑坐标空间(以点度量)映射到设备坐标空间(以像素度量)。这个值一般是1.0或2.0。较高的比例因子表示视图中的每一个点都由底层的多个像素表示。例如,若是比例因子为2.0,视图帧大小为50 x 50点,则用于显示该内容的位图的大小为100 x 100像素。
此属性的默认值是与当前显示视图的屏幕相关联的比例因子。若是自定义视图实现了一个自定义的drawRect:方法而且与一个窗口相关联,或者若是使用GLKView类来绘制OpenGL ES内容,你的视图以屏幕的全分辨率绘制。对于系统视图,即便在高分辨率屏幕上,这个属性的值也多是1.0。
一般,不须要修改此属性中的值。可是,若是你的应用程序使用OpenGL ES绘图,你可能想要改变比例因子以牺牲图像质量来换取渲染性能。
@property(nonatomic) CGFloat contentScaleFactor API_AVAILABLE(ios(4.0));
复制代码
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled API_UNAVAILABLE(tvOS);
属性描述 : 一个布尔值,指示视图一次是否接收到多个触摸。当设置为YES时,视图会接收与多点触摸序列相关的全部触摸,并在视图的边界内开始。当设置为NO时,视图只接收在视图边界内开始的多点触摸序列中的第一个触摸事件。此属性的默认值为NO。
此属性不影响附加到视图的手势识别器。手势识别器接收视图中发生的全部触摸。
当此属性为NO时,同一窗口中的其余视图仍然能够接收触摸事件。若是但愿该视图专门处理多点触摸事件,请将此属性和exclusiveTouch属性的值设置为YES。这个属性不会阻止视图被要求处理多个触摸。例如,两个子视图可能都将它们的触摸转发到一个共同的父视图,例如一个窗口或一个视图控制器的根视图。这个属性决定有多少最初针对视图的触摸被传递到那个视图。
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled API_UNAVAILABLE(tvOS);
复制代码
@property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch API_UNAVAILABLE(tvOS);
属性描述 : 一个布尔值,指示接收器是否以独占方式处理触摸事件。将此属性设置为YES会致使接收器阻止将触摸事件传递到同一窗口中的其余视图。此属性的默认值为NO。
@property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch API_UNAVAILABLE(tvOS);
复制代码
@property(nonatomic) BOOL autoresizesSubviews;
属性描述 : 一个布尔值,用于肯定接收器在其边界更改时是否自动调整其子视图的大小。设置为YES时,接收器在其边界更改时调整其子视图的大小。默认值为YES。
@property(nonatomic) BOOL autoresizesSubviews;
复制代码
@property(nonatomic) UIViewAutoresizing autoresizingMask;
属性描述 :一个整数位掩码,用于肯定接收器在其父视图的边界更改时如何调整自身大小。当视图的边界更改时,该视图会根据每一个子视图的自动调整大小掩码自动调整其子视图的大小。经过使用C位或运算符组合UIViewAutoresizing中描述的常量,能够指定此掩码的值。经过组合这些常量,能够指定视图的哪些维度应相对于父视图增大或缩小。此属性的默认值为UIViewAutoresizingNone,这表示不该调整视图的大小。
当沿同一轴设置多个选项时,默认行为是在柔性部分之间按比例分布大小差。与其余柔性部分相比,柔性部分越大,增加的可能性就越大。例如,假设此属性包括UIViewAutoresizingFlexibleWidth和UIViewAutoresizingFlexibleRightMargin常量,但不包括UIViewAutoresizingFlexibleLeftMargin常量,从而指示视图左边距的宽度是固定的,但视图的宽度和右边距可能会更改。所以,当视图宽度和视图右侧的间隙都增大时,视图将锚定在其父视图的左侧。
若是自动调整大小的行为不提供视图所需的精确布局,则可使用自定义容器视图并重写其layout subviews方法以更精确地定位子视图。
@property(nonatomic) UIViewAutoresizing autoresizingMask;
复制代码
UIViewAutoresizing的枚举值 :
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
//用于指示视图不调整大小的选项。
UIViewAutoresizingNone = 0,
//经过在左边距方向上展开或缩小视图来调整大小
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
//经过扩展或缩小视图宽度来调整大小
UIViewAutoresizingFlexibleWidth = 1 << 1,
//经过在右边距方向上展开或缩小视图来调整大小
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
//经过在上边距方向上展开或缩小视图来调整大小
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
//经过扩大或缩小视图的高度来调整大小
UIViewAutoresizingFlexibleHeight = 1 << 4,
//经过在下边距方向上展开或缩小视图来调整大小
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
复制代码
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers API_AVAILABLE(ios(3.2));
属性描述:当前附加到视图的手势识别器对象。每一个对象都是抽象基类UIGestureRecognitizer的子类的实例。此属性的默认值为零。若是添加手势识别器,而后将其删除,则该属性的值为空数组。
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers API_AVAILABLE(ios(3.2));
复制代码
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
函数描述 : 返回视图层次结构中包含指定点的接收者(包括它本身)的最远子代。这个方法经过调用每一个子视图的pointInside:withEvent:方法来遍历视图层次结构,以肯定哪一个子视图应该接收一个触摸事件。若是pointInside:withEvent:返回YES,那么子视图的层次结构将被遍历,直到发现包含指定点的最前面的视图为止。若是视图不包含该点,则忽略其视图层次结构的分支。不多须要本身调用这个方法,可是能够重写它来对子视图隐藏触摸事件。
此方法忽略隐藏、禁用用户交互或alpha级别小于0.01的视图对象的过滤。此方法在肯定点击时不考虑视图的内容。所以,即便指定的点位于视图内容的透明部分中,仍能够返回该视图。
位于接收器边界以外的点永远不会报告为点击,即便它们实际上位于接收器的子视图中。若是当前视图的clipsToBounds属性设置为NO,而且受影响的子视图超出了视图的边界,则可能会发生这种状况。
参数 :
point : 在接收器的局部坐标系(边界)中指定的点。
event : 保证调用此方法的事件。若是从事件处理代码外部调用此方法,则能够指定nil。
返回值 : 视图对象,它是当前视图的最远子代,包含点。若是点彻底位于接收器的视图层次结构以外,则返回nil。
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
复制代码
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
函数描述 : 返回一个布尔值,该值指示接收器是否包含指定的点。
参数 :
point : 在接收器的局部坐标系(边界)中的点。
event : 保证调用此方法的事件。若是从事件处理代码外部调用此方法,则能够指定nil。
返回值 : 若是点在接收器的范围内,则为YES;不然为NO。
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
复制代码
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
函数描述 : 将点从接收者的坐标系统转换为指定视图的坐标系统。
参数 :
point : 在接收器的局部坐标系(边界)中指定的点。
view : 要转换到其坐标系点的视图。若是view为nil,则此方法将转换为窗口基坐标。不然,视图和接收器必须属于同一个UIWindow对象。
返回值 : 转换为视图坐标系的点。
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
复制代码
简单的示例,例如使超出父视图的范围的按钮部分响应点击
@interface testView : UIView
@property (nonatomic, strong)UIButton *testCodeButton;
@end
@implementation testView
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if(self){
self.testCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.testCodeButton.backgroundColor = [UIColor blueColor];
self.testCodeButton.alpha = 0.5;
self.testCodeButton.titleLabel.font = [UIFont systemFontOfSize:15];
[self.testCodeButton setTitle:@"测试代码" forState:UIControlStateNormal];
[self.testCodeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[self addSubview:self.testCodeButton];
[self.testCodeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.mas_top).offset(-35);
make.centerX.equalTo(self);
make.size.mas_equalTo(CGSizeMake(150, 55));
}];
}
return self;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if ([view isKindOfClass:[UIButton class]]) {
return view;
}else if (view == nil) {
// 转换坐标系
CGPoint newPoint = [self.testCodeButton convertPoint:point fromView:self];
// 判断触摸点是否在button上
if (CGRectContainsPoint(self.testCodeButton.bounds, newPoint)) {
view = self.testCodeButton;
}
}
return view;
}
@end
@interface TestCodeController ()
@property (nonatomic, strong) testView *tview;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代码控制器";
self.tview = [[testView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.tview.backgroundColor = [UIColor redColor];
[self.tview.testCodeButton addTarget:self action:@selector(testCode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.tview];
}
///测试按钮点击
- (void)testCode{
YSUIntent *intent = [[YSUIntent alloc]initWithClassName:@"ShadowViewController"];
intent.useNavigationToPush = YES;
intent.method = OPEN_METHOD_POP;
[self openIntent:intent];
}
@end
复制代码
没有实现hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event函数时:
实现hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event函数时:
- (CGSize)sizeThatFits:(CGSize)size;
函数描述 :要求视图计算并返回最适合指定大小的大小。此方法的默认实现将返回视图的现有大小。子类能够重写此方法,以根据任何子视图的指望布局返回自定义值。例如,一个UISwitch对象返回一个固定大小值,该值表示一个switch视图的标准大小,而一个UIImageView对象返回它当前显示的图像的大小。此方法不调整接收器的大小。
参数 :
size : 视图应计算其最佳拟合大小的大小
返回值 : 适合接收者子视图的新大小。
- (CGSize)sizeThatFits:(CGSize)size;
复制代码
- (void)sizeToFit;
函数描述 : 调整接收器视图的大小并移动它,使其将它的子视图括起来。若是要调整当前视图的大小以使其使用最合适的空间量,请调用此方法。特定的UIKit视图根据本身的内部需求调整本身的大小。在某些状况下,若是视图没有超视图,它可能会根据屏幕边界调整自身大小。所以,若是但愿给定视图将自身调整为其父视图的大小,则应在调用此方法以前将其添加到父视图。
不该重写此方法。若是要更改视图的默认大小信息,请改成重写sizeThatFits:。该方法执行任何所需的计算并将其返回给该方法,而后由该方法进行更改。
- (void)sizeToFit;
复制代码
注:通常在使用UILabel的时候会用到,使用这两个方法以前,必需要给label赋值,不然不会显示内容的。sizeThatFits会计算出最优的 size 可是不会改变 本身的 size。sizeToFit会计算出最优的 size 并且会改变本身的size。
- (void)removeFromSuperview;
函数描述 : 从父视图及其窗口中取消视图的连接,并将其从响应链中移除。若是视图的父视图不是nil,则父视图释放该视图。调用此方法将删除指向要删除的视图的任何约束,或指向要删除的视图的子树中的任何视图的约束。
注 : 永远不要从视图的drawRect:方法中调用这个方法。
- (void)removeFromSuperview;
复制代码
例如处理 bug,当页面刷新的时候,状况是这样的:
想到的解决办法就是在每次刷新前将视图中的子视图移除:
makeObjectsPerformSelector :简化循环代码,数组的每一个元素都会执行@selector(removeFromSuperview)指定的removeFromSuperview方法。前提是元素的类型要拥有这个方法,不然会出现unrecognized selector sent to instance错误。
removeFromSuperview :将当前视图从其父视图移除。
[self.imgBackView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
复制代码
- (void)removeFromSuperview{
[self.imgBackView.subviews enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull subView, NSUInteger idx, BOOL * _Nonnull stop) {
[subView removeFromSuperview];
}];
}
复制代码
处理完在此频繁刷新,是这样的:
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
函数描述 : 在指定的索引处插入子视图。该方法创建了视图的强引用,并将它的下一个响应器设置为接收器,这是它的新父视图。视图只能有一个父视图。若是视图已经有一个父视图,而该视图不是接收器(接收器指调用函数的对象),则此方法在使接收器成为其新父视图以前删除先前的父视图。
参数 :
view : 要插入的视图。这个值不能为空。
index : 要在其中插入视图的子视图属性数组中的索引。子视图索引从0开始,而且不能大于子视图的数量。
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
复制代码
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
函数描述 : 交换指定索引处的子视图。每一个索引表示子视图属性中数组中相应视图的位置。子视图索引从0开始,而且不能大于子视图的数量。这个方法不改变任何一个视图的父视图,而只是交换它们在子视图数组中的位置。
参数 :
index1 : 接收器中第一个子视图的索引。
index2 : 接收器中第二个子视图的索引。
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
复制代码
例如交换两个视图的层级:
@interface TestCodeController ()
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIView *view2;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代码控制器";
self.view1 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.view1.backgroundColor = [UIColor redColor];
[self.view addSubview:self.view1];
self.view2 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.view2.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.view2];
UIButton *testCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
testCodeButton.frame = CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 75 / 2, CGRectGetMaxY(self.view1.frame) + 20, 75, 30);
testCodeButton.backgroundColor = [UIColor blueColor];
testCodeButton.titleLabel.font = [UIFont systemFontOfSize:15];
[testCodeButton setTitle:@"测试代码" forState:UIControlStateNormal];
[testCodeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[testCodeButton addTarget:self action:@selector(testCode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:testCodeButton];
}
///测试按钮点击
- (void)testCode{
[self testexchangeSubviewAtIndex:self.view1 andView:self.view2];
}
///交换视图层级
- (void)testexchangeSubviewAtIndex:(UIView *)view1 andView:(UIView *)view2{
NSInteger index1 = 0;
NSInteger index2 = 0;
for (int i = 0; i < self.view.subviews.count; i++) {
if([self.view.subviews[i] isEqual:view1]){
index1 = I;
}else if([self.view.subviews[i] isEqual:view2]){
index2 = I;
}
}
if(index1 != index2){
[self.view exchangeSubviewAtIndex:index1 withSubviewAtIndex:index2];
}
}
复制代码
效果如图:
- (void)addSubview:(UIView *)view;
函数描述 : 将视图添加到接收器的子视图列表的末尾。该方法创建了视图的强引用,并将它的下一个响应器设置为接收器,这是它的新父视图。视图只能有一个父视图。若是视图已经有一个父视图,而该视图不是接收方,则此方法在使接收器成为其新父视图以前删除先前的父视图。
参数 :
view : 要添加的视图。添加后,此视图将出如今任何其余子视图之上。
- (void)addSubview:(UIView *)view;
复制代码
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
函数描述 : 在视图层次结构中的另外一个视图下方插入视图。该方法创建了视图的强引用,并将它的下一个响应器设置为接收器,这是它的新父视图。视图只能有一个父视图。若是视图已经有一个父视图,而该视图不是接收器,则此方法在使接收器成为其新父视图以前删除先前的父视图。
参数 :
view : 要在另外一个视图下插入的视图。若是它不是siblingSubview的同级,则从其superview中移除。
siblingSubview : 插入视图上方的同级视图。
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
复制代码
例如在视图层次结构中的另外一个视图下方插入视图:
#import "TestCodeController.h"
@interface TestCodeController ()
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIView *view2;
@property (nonatomic, strong) UIView *view3;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代码控制器";
self.view1 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.view1.backgroundColor = [UIColor redColor];
[self.view addSubview:self.view1];
self.view2 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 30, 150, 150)];
self.view2.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.view2];
self.view3 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 15, 150, 150)];
self.view3.backgroundColor = [UIColor yellowColor];
UIButton *testCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
testCodeButton.frame = CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 75 / 2, CGRectGetMaxY(self.view1.frame) + 40, 75, 30);
testCodeButton.backgroundColor = [UIColor blueColor];
testCodeButton.titleLabel.font = [UIFont systemFontOfSize:15];
[testCodeButton setTitle:@"测试代码" forState:UIControlStateNormal];
[testCodeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[testCodeButton addTarget:self action:@selector(testCode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:testCodeButton];
}
///测试按钮点击
- (void)testCode{
[self testInsertSubview:self.view3 belowSubview:self.view2];
}
///在视图层次结构中的另外一个视图下方插入视图
- (void)testInsertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview{
[self.view insertSubview:view belowSubview:siblingSubview];
}
复制代码
效果如图 :
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
函数描述 : 在视图层次结构中的另外一个视图上方插入视图。此方法创建对视图的强引用,并将其下一个响应者设置为接收器,这是它的新父视图。视图只能有一个父视图。若是视图已经有一个父视图,而该视图不是接收器,则此方法在使接收器成为其新父视图以前删除先前的父视图。
参数 :
view : 要插入的视图。若是它不是siblingSubview的同级,则从其superview中移除。
siblingSubview : 插入的视图下面的同级视图。
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
复制代码
- (void)bringSubviewToFront:(UIView *)view;
函数描述 : 移动指定的子视图,使其显示在其同级视图的顶部。此方法将指定的视图移动到“subviews ”属性中视图数组的末尾。
参数 :
view : 要移到前面的子视图。
- (void)bringSubviewToFront:(UIView *)view;
复制代码
例如移动指定的子视图,使其显示在其同级视图的顶部:
#import "TestCodeController.h"
@interface TestCodeController ()
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIView *view2;
@property (nonatomic, strong) UIView *view3;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代码控制器";
self.view1 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.view1.backgroundColor = [UIColor redColor];
[self.view addSubview:self.view1];
self.view2 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 30, 150, 150)];
self.view2.backgroundColor = [UIColor greenColor];
[self.view addSubview:self.view2];
self.view3 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 15, 150, 150)];
self.view3.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.view3];
UIButton *testCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
testCodeButton.frame = CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 75 / 2, CGRectGetMaxY(self.view1.frame) + 40, 75, 30);
testCodeButton.backgroundColor = [UIColor blueColor];
testCodeButton.titleLabel.font = [UIFont systemFontOfSize:15];
[testCodeButton setTitle:@"测试代码" forState:UIControlStateNormal];
[testCodeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[testCodeButton addTarget:self action:@selector(testCode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:testCodeButton];
}
///测试按钮点击
- (void)testCode{
[self testBringSubviewToFront:self.view1];
}
///移动指定的子视图,使其显示在其同级视图的顶部
- (void)testBringSubviewToFront:(UIView *)view{
[self.view bringSubviewToFront:view];
}
复制代码
效果如图 :
- (void)sendSubviewToBack:(UIView *)view;
函数描述 : 移动指定的子视图,使其显示在其同级视图的后面。此方法将指定的视图移动到“subviews”属性中视图数组的开头。
参数 :
view : 要移到后面的子视图。
- (void)sendSubviewToBack:(UIView *)view;
复制代码
- (void)didAddSubview:(UIView *)subview;
函数描述 : 告诉视图已添加子视图。此方法的默认实现不起任何做用。子类能够重写它,以便在添加子视图时执行其余操做。此方法是在使用任何相关视图方法添加子视图时调用的。
参数 :
subview : 做为子视图添加的视图。
- (void)didAddSubview:(UIView *)subview;
复制代码
例如 :
@interface TestView : UIView
@property (nonatomic, assign) NSInteger number;
@end
@implementation TestView
- (void)didAddSubview:(UIView *)subview{
[super didAddSubview:subview];
self.number += 1;
NSLog(@"添加%ld次视图了",(long)self.number);
}
@end
@interface TestCodeController ()
@property (nonatomic, strong) TestView *contentView;
@property (nonatomic, strong) UIView *view1;
@property (nonatomic, strong) UIView *view2;
@property (nonatomic, strong) UIView *view3;
@end
@implementation TestCodeController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = @"测试代码控制器";
self.contentView = [[TestView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame))];
[self.view addSubview:self.contentView];
self.view1 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMaxY(self.view.frame) / 2 - 150 / 2, 150, 150)];
self.view1.backgroundColor = [UIColor redColor];
[self.contentView addSubview:self.view1];
self.view2 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 30, 150, 150)];
self.view2.backgroundColor = [UIColor greenColor];
[self.contentView addSubview:self.view2];
self.view3 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 150 / 2, CGRectGetMinY(self.view1.frame) + 15, 150, 150)];
self.view3.backgroundColor = [UIColor yellowColor];
[self.contentView addSubview:self.view3];
UIButton *testCodeButton = [UIButton buttonWithType:UIButtonTypeCustom];
testCodeButton.frame = CGRectMake(CGRectGetMaxX(self.view.frame) / 2 - 75 / 2, CGRectGetMaxY(self.view1.frame) + 40, 75, 30);
testCodeButton.backgroundColor = [UIColor blueColor];
testCodeButton.titleLabel.font = [UIFont systemFontOfSize:15];
[testCodeButton setTitle:@"测试代码" forState:UIControlStateNormal];
[testCodeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[testCodeButton addTarget:self action:@selector(testCode) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:testCodeButton];
}
复制代码
输出如图 :
- (void)willRemoveSubview:(UIView *)subview;
函数描述 : 告诉视图子视图即将被删除。此方法的默认实现不起任何做用。子类能够重写它,以便在删除子视图时执行其余操做。当子视图的父视图更改或子视图从视图层次结构中彻底删除时,将调用此方法。
参数 :
subview : 将被删除的子视图。
- (void)willRemoveSubview:(UIView *)subview;
复制代码
- (void)layoutSubviews;
函数描述 : 在某个类的内部调整子视图位置时,须要调用这个方法,默认没有作任何事情,须要子类进行重写 。 系统在不少时候会去调用这个方法,初始化不会触发layoutSubviews,可是若是设置了不为CGRectZero的frame并添加到父视图的时候就会触发,要在实现的最后调用[super layoutSubviews]。不该直接调用此方法。若是要强制进行布局更新,请在下次图形更新以前调用setNeedsLayout方法。若是要当即更新视图的布局,请调用layoutIfNeeded方法。
layoutSubviews方法的触发: 1.直接调用[self setNeedsLayout]; 2.addSubview的时候。 3.当view的size发生改变的时候,前提是frame的值设置先后发生了变化。 4.滑动UIScrollView的时候。 5.旋转Screen会触发父UIView上的layoutSubviews事件
- (void)layoutSubviews;
复制代码
一般也能够在layoutSubviews函数中对表视图的cell添加CALayer对象进行布局操做,好比添加分割线或者渐变图层,这里以简单的添加分割线为例,例如添加相似的分割线:
若是在表视图的cell初始化时添加CALayer,经过self.contentView.frame获取的宽高一般不许确。
cell初始化函数中添加CALayer的代码片断:
///底部分割线
self.separatorLineLayer = [[CALayer alloc] init];
NSLog(@"%f",CGRectGetHeight(self.contentView.frame));
NSLog(@"%f",CGRectGetWidth(self.contentView.frame));
self.separatorLineLayer.frame = CGRectMake(0, CGRectGetHeight(self.contentView.frame) - 0.5, CGRectGetWidth(self.contentView.frame), 0.6);
[self.contentView.layer addSublayer:_separatorLineLayer];
self.separatorLineLayer.backgroundColor = [UIColor grayColor].CGColor;
复制代码
打印的结果为:
视图样式为:
为了更加精确的布局cell中的CALayer对象,则能够在cell初始化函数中初始化做为分割线的CALayer对象,但不设置frame,将frame在layoutSubviews中进行布局,则能获得更为 精确的布局。
cell初始化函数中添加CALayer的代码片断:
///底部分割线
self.separatorLineLayer = [[CALayer alloc] init];
[self.contentView.layer addSublayer:_separatorLineLayer];
self.separatorLineLayer.backgroundColor = [UIColor grayColor].CGColor;
复制代码
在layoutSubviews函数中设置frame的代码片断:
///底部分割线
- (void)layoutSubviews {
[super layoutSubviews];
NSLog(@"%f",CGRectGetHeight(self.contentView.frame));
NSLog(@"%f",CGRectGetWidth(self.contentView.frame));
self.separatorLineLayer.frame = CGRectMake(0, CGRectGetHeight(self.contentView.frame) - 0.5, CGRectGetWidth(self.contentView.frame), 0.6);
}
复制代码
打印的结果为:
视图样式为:
- (void)setNeedsLayout;
函数描述 : 使接收器的当前布局无效,并在下一个更新周期中触发布局更新。若是要调整视图子视图的布局,请在应用程序的主线程上调用此方法。此方法记录请求并当即返回。因为此方法不强制当即更新,而是等待下一个更新周期,所以可使用它在更新任何视图以前使多个视图的布局无效。此行为容许您将全部布局更新合并到一个更新周期,这一般对性能更好。
设置布局,告知系统这个视图须要更新布局,这个方法会当即返回,可是view会在下一次的更新周期中更新,调用视图的layoutSubviews。
- (void)setNeedsLayout;
复制代码
例如 :
- (void)setBgColor:(UIColor *)bgColor {
_bgColor = bgColor;
self.backgroundColor = bgColor;
[self setNeedsLayout];
}
复制代码
- (void)layoutIfNeeded;
函数描述 : 若是布局更新挂起,则当即布局子视图。使用此方法强制视图当即更新其布局。使用自动布局时,布局引擎根据须要更新视图的位置,以知足约束的更改。使用接收消息的视图做为根视图,此方法从根开始布置视图子树。若是没有更新布局,则该方法退出而不修改布局或调用任何与布局相关的回调。
layoutIfNeeded不必定会触发view的layoutSubviews。系统会检测layoutSubviews的触发条件,若是符合条件,那么会当即触发layoutSubviews,不会等待下一次的更新周期。但若是不符合layoutSubviews的触发条件则不会触发。
- (void)layoutIfNeeded;
复制代码
例如 :在视图动画块代码中使用Masonry更改布局,在调用layoutIfNeeded后才会触发动画:
[UIView animateWithDuration:1 animations:^{
[self.customSelectRecurrenceView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.view.mas_bottom).offset(-YSLCommonPadding * 2);
make.centerX.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(SCREEN_WIDTH - 20, 540));
}];
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
self.repetitionModeTableView.hidden = YES;
}];
复制代码
@property(nonatomic) BOOL clipsToBounds;
属性描述 : 一个布尔值,用于肯定子视图是否限制在视图的边界内。将此值设置为“YES”将致使子视图被剪裁到接收器的边界。若是设置为“NO”,则不会剪裁帧超出接收器可见边界的子视图。默认值为NO。
@property(nonatomic) BOOL clipsToBounds;
复制代码
@property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
属性描述 : 视图的背景色。对此属性的更改能够设置动画。默认值为nil,这将产生透明的背景色。
@property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
复制代码
@property(nonatomic) CGFloat alpha;
属性描述:视图的alpha值。此属性的值是介于0.0到1.0之间的浮点数,其中0.0表示彻底透明,1.0表示彻底不透明。更改此属性的值仅更新当前视图的alpha值。可是,该alpha值赋予的透明度会影响视图的全部内容,包括其子视图。例如,嵌入到alpha值为0.5的父视图中的alpha值为1.0的子视图将显示在屏幕上,就好像它的alpha值也是0.5同样。对此属性的更改能够设置动画。
@property(nonatomic) CGFloat alpha;
复制代码
@property(nonatomic,getter=isOpaque) BOOL opaque;
属性描述 : 决定视图是否不透明的布尔值。这个属性向绘图系统提供了应该如何处理视图的提示。若是设置为YES,绘图系统将视图视为彻底不透明的,这容许绘图系统优化一些绘图操做并提升性能。若是设置为NO,绘图系统将正常地将视图与其余内容组合在一块儿。这个属性的默认值是YES。
不透明视图应该用彻底不透明的内容填充其边界——也就是说,内容的alpha值应该为1.0。若是视图是不透明的,或者没有填充其边界,或者包含彻底或部分透明的内容,结果是不可预测的。若是视图是彻底或部分透明的,则应该始终将此属性的值设置为NO。
只须要在UIView的子类中为opaque属性设置一个值,这些子类使用drawRect:方法绘制本身的内容。不透明属性在系统提供的类(如UIButton、UILabel、UITableViewCell等)中不起做用。
@property(nonatomic,getter=isOpaque) BOOL opaque;
复制代码
@property(nonatomic) BOOL clearsContextBeforeDrawing;
属性描述 : 一个布尔值,用来决定是否在绘制前自动清除视图的边界。当设置为YES时,绘制缓冲区在调用drawRect:方法以前自动清除为透明黑色。此行为可确保在从新绘制视图内容时不会留下任何视觉瑕疵。若是视图的opaque属性也设置为YES,则视图的backgroundColor属性不能为nil,不然可能会出现绘制错误。这个属性的默认值是YES。
若是将此属性的值设置为NO,则负责确保在drawRect:方法中正确绘制视图的内容。若是图形代码已经进行了大量优化,则将此属性设置为“否”能够提升性能,尤为是在滚动视图时,可能只须要从新绘制视图的一部分。
@property(nonatomic) BOOL clearsContextBeforeDrawing;
复制代码
@property(nonatomic,getter=isHidden) BOOL hidden;
属性描述 : 肯定视图是否隐藏的布尔值。将此属性的值设置为“YES”将隐藏接收器,将其设置为“NO”将显示接收器。默认值为“NO”。
隐藏视图将从其窗口中消失,而且不接收输入事件。不过,它仍保留在其superview的子视图列表中,并像往常同样参与自动调整大小。隐藏包含子视图的视图的效果是隐藏这些子视图及其可能具备的任何视图后代。这种效果是隐式的,不会改变接收者后代的隐藏状态。
隐藏做为窗口当前第一响应程序的视图会致使视图的下一个有效键视图成为新的第一响应程序。
此属性的值仅反映接收器的状态,而不说明接收器祖先在视图层次结构中的状态。所以,这个属性能够是NO,可是若是一个祖先是隐藏的,那么接收者可能仍然是隐藏的。
@property(nonatomic,getter=isHidden) BOOL hidden;
复制代码
@property(nonatomic) UIViewContentMode contentMode;
属性描述:当视图的边界改变时,用来肯定视图如何布局其内容的标志。内容模式指定了当视图的边界改变时如何调整缓存的视图层位图。此属性一般用于实现可调整大小的控件。不用每次都从新绘制视图的内容,可使用此属性来指定但愿缩放内容(有或没有失真)或将它们固定到视图上的一个特定位置。
@property(nonatomic) UIViewContentMode contentMode;
复制代码
UIViewContentMode的枚举值
typedef NS_ENUM(NSInteger, UIViewContentMode) {
//根据须要经过更改内容的纵横比来缩放内容以适合其自身大小的选项。
//UIImageView使用时,图片拉伸填充至整个UIImageView(图片可能会变形)
UIViewContentModeScaleToFill,
//经过保持纵横比缩放内容以适应视图大小的选项。视图边界的任何剩余区域都是透明的。
//UIImageView使用时,图片拉伸至彻底显示在UIImageView里面为止(图片不会变形),但可能长或宽某一方向留白
UIViewContentModeScaleAspectFit,
//缩放内容以填充视图大小的选项。内容的某些部分可能会被剪裁以填充视图的边界。
//UIImageView使用时,图片拉伸至彻底显示在UIImageView里面为止(图片不会变形),但可能超过UIImageView的边界而被裁减
UIViewContentModeScaleAspectFill,
//当边界改变时经过调用setNeedsDisplay方法从新显示视图的选项。
UIViewContentModeRedraw,
//使内容在视图边界居中的选项,保持比例不变。
UIViewContentModeCenter,
//将内容居中对齐视图边界顶部的选项。
UIViewContentModeTop,
//使内容在视图边界的底部居中的选项
UIViewContentModeBottom,
//在视图左侧对齐内容的选项。
UIViewContentModeLeft,
//在视图右侧对齐内容的选项。
UIViewContentModeRight,
//在视图左上角对齐内容的选项。
UIViewContentModeTopLeft,
//在视图右上角对齐内容的选项。
UIViewContentModeTopRight,
//对齐视图左下角内容的选项。
UIViewContentModeBottomLeft,
//对齐视图右下角内容的选项。
UIViewContentModeBottomRight,
};
复制代码
- (void)setNeedsDisplay;
将接收者的整个边界矩形标记为须要从新绘制。可使用此方法或setNeedsDisplayInRect:通知系统须要从新绘制视图的内容。此方法记录请求并当即返回。直到下一个绘图周期(此时将更新全部无效的视图)时,视图才实际从新绘制。
若是你的视图是由一个CAEAGLLayer对象支持的,这个方法没有效果。它只用于使用本地绘图技术(如UIKit和Core Graphics)来呈现内容的视图。应该使用此方法来请求仅在视图的内容或外观更改时从新绘制视图。若是只是更改视图的几何形状,则一般不会从新绘制视图。相反,它的现有内容是根据视图的contentMode属性中的值进行调整的。从新显示现有内容能够避免从新绘制内容,从而提升性能
与setNeedsLayout方法类似。该方法在调用时,会自动调用drawRect方法。drawRect方法主要用来画图。因此,当须要刷新布局时,用setNeedsLayout方法;当须要从新绘画时,调用setNeedsDisplay方法。
- (void)setNeedsDisplay;
复制代码
例如 :
- (void)setFillColor:(UIColor *)fillColor {
if (fillColor) {
_fillColor = fillColor;
} else {
_fillColor = [UIColor whiteColor];
}
[self setNeedsDisplay];
}
复制代码
- (void)drawRect:(CGRect)rect;
属性描述 : 该方法默认在视图加载过程当中不作任何处理,当子类绘制视图内容时就能够在该方法中添加绘制的代码。若是在UIView初始化时没有设置Rect大小,将直接致使drawRect不被自动调用。若是设置了Rect,能够直接调用setNeedsDisplay触发。若是视图以其余方式设置其内容,则不须要重写此方法。例如,若是视图仅显示背景色,或者视图直接使用基础层对象设置其内容,则不须要重写此方法。
在调用此方法时,UIKit已经为视图配置了适当的绘图环境,能够简单地调用渲染内容所需的任何绘图方法和函数。具体来讲,UIKit建立和配置图形上下文,并调整该上下文的转换,使其原点与视图边框矩形的原点匹配。可使用UIGraphicsGetCurrentContext函数获取对图形上下文的引用,但不要创建对图形上下文的强引用,由于它能够在对drawRect:方法的调用之间进行更改。
此方法在首次显示视图或发生使视图的可见部分无效的事件时调用。你不该该本身直接调用这个方法。若要使视图的一部分无效,从而致使该部分被重绘,请改成调用setNeedsDisplay或setNeedsDisplayInRect:方法。
参数 :
rect : 视图边界中须要更新的部分。第一次绘制视图时,这个矩形一般是视图的整个可见边界。可是,在随后的绘图操做期间,矩形可能只指定视图的一部分。
- (void)drawRect:(CGRect)rect;
复制代码
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations API_AVAILABLE(ios(4.0));
函数描述 : 使用指定的持续时间对一个或多个视图的更改设置动画。此方法使用UIViewAnimationOptionCurveEaseInOut和UIViewAnimationOptionTransitionNone动画选项当即执行指定的动画。
在动画期间,将暂时禁用正在设置动画的视图的用户交互。(在iOS 5以前,对整个应用程序禁用用户交互。)
参数 :
duration : 动画的总持续时间,以秒为单位。若是指定负值或0,则在不设置动画的状况下进行更改。
animations : 包含要提交到视图的更改的块对象。这是以编程方式更改视图层次结构中视图的任何可设置动画的属性的地方。此块不接受任何参数,也没有返回值。此参数不能为NULL。
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations API_AVAILABLE(ios(4.0));
复制代码
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));
函数描述 : 使用指定的持续时间和完成处理程序为一个或多个视图的更改设置动画。此方法使用UIViewAnimationOptionCurveEaseInOut和UIViewAnimationOptionTransitionNone动画选项当即执行指定的动画。
在动画期间,将暂时禁用正在设置动画的视图的用户交互。(在iOS 5以前,对整个应用程序禁用用户交互。)
参数 :
duration : 动画的总持续时间,以秒为单位。若是指定负值或0,则在不设置动画的状况下进行更改。
animations : 包含要提交到视图的更改的块对象。这是以编程方式更改视图层次结构中视图的任何可设置动画的属性的地方。此块不接受任何参数,也没有返回值。此参数不能为NULL。
completion : 动画序列结束时执行的块对象。这个块没有返回值,只有一个布尔参数,用来指示动画在完成处理程序被调用以前是否已经完成。若是动画的持续时间是0,这个块将在下一个运行循环的开始执行。该参数能够为NULL。
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));
复制代码
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));
函数描述:使用指定的持续时间、延迟、选项和完成处理程序为一个或多个视图的更改设置动画。
此方法启动一组要在视图上执行的动画。animations参数中的block对象包含用于设置一个或多个视图特性动画的代码。
在动画期间,将暂时禁用正在设置动画的视图的用户交互。(在iOS 5以前,对整个应用程序禁用用户交互。)若是但愿用户可以与视图交互,请在options参数中包含UIViewAnimationOptionAllowUserInteraction常量。
参数 :
duration : 动画的总持续时间,以秒为单位。若是指定负值或0,则在不设置动画的状况下进行更改。
delay :开始动画以前等待的时间量(以秒为单位)。指定值0以当即开始动画。
options : 指示如何执行动画的选项掩码。
animations : 包含要提交到视图的更改的块对象。这是以编程方式更改视图层次结构中视图的任何可设置动画的属性的地方。此块不接受任何参数,也没有返回值。此参数不能为NULL。
completion : 动画序列结束时执行的块对象。这个块没有返回值,只有一个布尔参数,用来指示动画在完成处理程序被调用以前是否已经完成。若是动画的持续时间是0,这个块将在下一个运行循环的开始执行。该参数能够为空。
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0));
复制代码
简单的练习代码片断:
- (void)testAnimationBlock{
//建立测试动画的标签
UILabel *animationLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, CGRectGetMaxY(self.view.frame) / 2, 200, 20)];
animationLabel.textColor = [UIColor whiteColor];
animationLabel.backgroundColor = [UIColor blueColor];
animationLabel.text = @"我出现后就准备跑路了";
animationLabel.textAlignment = NSTextAlignmentCenter;
animationLabel.layer.cornerRadius = 8.0;
animationLabel.layer.masksToBounds = YES;
animationLabel.alpha = 0.0;
[self.view addSubview:animationLabel];
[UIView animateWithDuration:5.0 delay:10.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
animationLabel.alpha = 1.0;
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.0 animations:^{
CGRect newAnimationLabelFrame = animationLabel.frame;
newAnimationLabelFrame.origin.x = CGRectGetMaxX(self.view.frame) - 200 - 20;
animationLabel.frame = newAnimationLabelFrame;
} completion:^(BOOL finished) {
animationLabel.text = @"我就跑路到这里吧";
}];
}];
}
复制代码
动画效果如图 :
@property(nonatomic, readonly) CGSize intrinsicContentSize API_AVAILABLE(ios(6.0));
属性描述 : 接收视图的天然大小,仅考虑视图自己的属性。自定义视图一般显示布局系统不知道的内容。经过设置此属性,自定义视图能够根据其内容与布局系统通讯其但愿的大小。这个内在大小必须独立于内容框架,由于例如,没法根据更改的高度将更改的宽度动态地传递给布局系统。若是自定义视图没有给定维度的内部大小,则能够对该维度使用UIViewNoIntrinsicMetric。
@property(nonatomic, readonly) CGSize intrinsicContentSize API_AVAILABLE(ios(6.0));
复制代码
例如在自定义导航视图时,添加按钮不响应点击事件:
能够在自定义的视图.h文件中覆盖intrinsicContentSize属性,在实例化自定义视图时设置intrinsicContentSize属性的值,例如 :
@interface YSCNavigationItemTitleView : UIView
@property(nonatomic, assign) CGSize intrinsicContentSize; //重写intrinsicContentSize属性
@property(nonatomic, strong) UILabel *titleLabel; //标题标签
@property(nonatomic, strong) UIButton *orderTypeSelectionButton; //订单类型选择按钮
@property(nonatomic, strong) UIButton *labelMakeButton;//标题标签遮罩按钮
@end
复制代码
- (void)createNavigationTitleView:(NSString *)text{
//初始化订单汇总的自定义标题视图
YSCNavigationItemTitleView *navigationItemTitleView = [[YSCNavigationItemTitleView alloc]initWithFrame:CGRectZero];
//计算文本矩形
CGRect rect = [navigationItemTitleView.titleLabel.text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, [YSCUiUtils singleCharactorSizeWithFont:[YSCUiUtils fontOne]].height) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:20]} context:nil];
//设置订单汇总的自定义标题视图大小
navigationItemTitleView.intrinsicContentSize = CGSizeMake(rect.size.width, [YSCUiUtils singleCharactorSizeWithFont:[YSCUiUtils fontOne]].height);
}
复制代码
- (void)updateConstraints API_AVAILABLE(ios(6.0)) NS_REQUIRES_SUPER;
函数描述 : 主要功能是更新view的约束,并会调用其全部子视图的该方法去更新约束。自定义视图应该经过重写此方法来设置更新本身的约束,而后调用setNeedsUpdateConstraints标记约束须要更新。系统在进行布局layout以前,会调用updateConstraints。要在实现的最后调用[super updateConstraints]。
注 :在发生影响的更改后当即更新约束几乎老是更干净和更容易的。例如,若是要响应按钮点击更改约束,请直接在按钮的操做方法中进行更改。
仅当在位更改约束太慢或视图正在生成大量冗余更改时,才应重写此方法。 要计划更改,请对视图调用setNeedsUpdateConstraints。而后,系统在布局发生以前调用updateConstraint的实现。能够在自定义视图的属性未更改时验证内容的全部必要约束是否已到位。
实现必须尽量高效。不要停用全部约束,而后从新激活所需的约束。相反,应用必须有某种方法来跟踪约束,并在每次更新过程当中验证它们。只更改须要更改的项。在每次更新过程当中,必须确保对应用程序的当前状态具备适当的约束。
不要在实现中调用setNeedsUpdateConstraints。调用setNeedsUpdateConstraints将调度另外一个更新遍历,建立一个反馈循环。 调用[super updateConstraints]做为实现的最后一步。
- (void)updateConstraints API_AVAILABLE(ios(6.0)) NS_REQUIRES_SUPER;
复制代码
- (void)layoutSubviews;
- (void)setNeedsLayout;
- (void)setNeedsDisplay;
- (void)layoutIfNeeded;
- (void)drawRect:(CGRect)rect;
- (CGSize)sizeThatFits:(CGSize)size;
- (void)sizeToFit;
- (void)updateConstraints;
- (void)setNeedsUpdateConstraints;
复制代码
- (void)updateViewConstraints API_AVAILABLE(ios(6.0));
函数描述 :当视图控制器的视图须要更新其约束时调用, updateViewConstraints的出现方便了viewController,不用专门去重写controller的view,当view的updateConstraints被调用时,该view如有controller,该controller的updateViewConstraints便会被调用。 要在实现的最后调用[super updateViewConstraints]。
- (void)updateViewConstraints API_AVAILABLE(ios(6.0));
复制代码