iOS UIView的学习笔记
2020/5/7 23:26:47
本文主要是介绍iOS UIView的学习笔记,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
UIView
UIView为屏幕上的矩形区域管理内容的对象。视图是应用程序用户界面的基本构建块,UIView类定义了所有视图通用的行为。视图对象呈现其边界矩形内的内容,并处理与该内容的任何交互。
UIView类是一个具体的类,您可以实例化它并使用它来显示固定的背景色。您还可以将其子类化以绘制更复杂的内容。要显示应用程序中常见的标签、图像、按钮和其他界面元素,请使用UIKit框架提供的视图子类,而不要试图定义自己的视图子类。
因为视图对象是应用程序与用户交互的主要方式,所以它们有许多职责。以下是一些:
- 绘图和动画
- 视图使用UIKit或核心图形在其矩形区域中绘制内容。
- 某些视图属性可以设置为新值的动画。
- 布局和子视图管理
- 视图可以包含零个或多个子视图。
- 视图可以调整其子视图的大小和位置。
- 使用自动布局来定义视图调整大小和重新定位的规则,以响应视图层次结构中的更改。
3.事件处理
- 视图是UIResponder的子类,可以响应触摸和其它类型的事件。
- 视图可以安装手势识别器来处理常见的手势。
- 视图可以嵌套在其他视图中以创建视图层次结构,这为组织相关内容提供了一种方便的方法。嵌套视图在嵌套的子视图(称为子视图)和父视图(称为父视图)之间创建父子关系。父视图可以包含任意数量的子视图,但每个子视图只有一个父视图。默认情况下,当子视图的可见区域超出其父视图的范围时,不会发生子视图内容的裁剪。使用clipsToBounds属性更改该行为。
- 每个视图的几何图形由其框架和边界属性定义。frame属性在其父视图的坐标系统中定义视图的原点和维度。bounds属性定义了视图看到的内部尺寸,并且几乎只在定制绘图代码中使用。center属性提供了一种方便的方法来重新定位视图,而无需直接更改其框架或边界属性。
UIView常用属性
@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(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); } 复制代码
UIView常用函数
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
函数描述 : 使用指定的框架矩形初始化并返回新分配的视图对象。新视图对象必须插入到窗口的视图层次结构中才能使用。如果以编程方式创建视图对象,则此方法是UIView类的指定初始值设定项。子类可以重写此方法以执行任何自定义初始化,但必须在其实现开始时调用super。
如果使用Interface Builder设计接口,则在随后从nib文件加载视图对象时不调用此方法。nib文件中的对象被重新构造,然后使用它们的initWithCoder:方法进行初始化,该方法修改视图的属性以匹配存储在nib文件中的属性。
参数 :
frame : 视图的边框矩形,以点为单位。框架的原点相对于要在其中添加它的超视图。此方法使用框架矩形相应地设置中心和边界属性。
返回值 : 初始化的视图对象。
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER; 复制代码
- (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; 复制代码
IOS中View进行layout方法
- (void)layoutSubviews; - (void)setNeedsLayout; - (void)setNeedsDisplay; - (void)layoutIfNeeded; - (void)drawRect:(CGRect)rect; - (CGSize)sizeThatFits:(CGSize)size; - (void)sizeToFit; - (void)updateConstraints; - (void)setNeedsUpdateConstraints; 复制代码
layoutSubviews
- (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; 复制代码
setNeedsLayout
- (void)setNeedsLayout;
函数描述 : 使接收器的当前布局无效,并在下一个更新周期中触发布局更新。如果要调整视图子视图的布局,请在应用程序的主线程上调用此方法。此方法记录请求并立即返回。由于此方法不强制立即更新,而是等待下一个更新周期,因此可以使用它在更新任何视图之前使多个视图的布局无效。此行为允许您将所有布局更新合并到一个更新周期,这通常对性能更好。
设置布局,告知系统这个视图需要更新布局,这个方法会立即返回,但是view会在下一次的更新周期中更新,调用视图的layoutSubviews。
- (void)setNeedsLayout; 复制代码
例如 :
- (void)setBgColor:(UIColor *)bgColor { _bgColor = bgColor; self.backgroundColor = bgColor; [self setNeedsLayout]; } 复制代码
setNeedsDisplay
- (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]; } 复制代码
layoutIfNeeded
- (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; }]; 复制代码
drawRect
- (void)drawRect:(CGRect)rect;
属性描述 : 该方法默认在视图加载过程中不做任何处理,当子类绘制视图内容时就可以在该方法中添加绘制的代码。如果在UIView初始化时没有设置Rect大小,将直接导致drawRect不被自动调用。如果设置了Rect,可以直接调用setNeedsDisplay触发。如果视图以其他方式设置其内容,则不需要重写此方法。例如,如果视图仅显示背景色,或者视图直接使用基础层对象设置其内容,则不需要重写此方法。
在调用此方法时,UIKit已经为视图配置了适当的绘图环境,可以简单地调用渲染内容所需的任何绘图方法和函数。具体来说,UIKit创建和配置图形上下文,并调整该上下文的转换,使其原点与视图边框矩形的原点匹配。可以使用UIGraphicsGetCurrentContext函数获取对图形上下文的引用,但不要建立对图形上下文的强引用,因为它可以在对drawRect:方法的调用之间进行更改。
此方法在首次显示视图或发生使视图的可见部分无效的事件时调用。你不应该自己直接调用这个方法。若要使视图的一部分无效,从而导致该部分被重绘,请改为调用setNeedsDisplay或setNeedsDisplayInRect:方法。
参数 :
rect : 视图边界中需要更新的部分。第一次绘制视图时,这个矩形通常是视图的整个可见边界。但是,在随后的绘图操作期间,矩形可能只指定视图的一部分。
- (void)drawRect:(CGRect)rect; 复制代码
sizeThatFits与sizeToFit
- (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。
updateConstraints
- (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; 复制代码
updateViewConstraints
- (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)); 复制代码
这篇关于iOS UIView的学习笔记的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值