一,View的内容区域指什么?
一个视图的内容区域指,在它内部展示内容的大小区域,例如,UILabel的内容区域是文字大小的区域,如下:
整个红色框包裹的区域,就是整个view的frame大小,那么蓝色框包括的区域,就是它的内容区域大小,内容区域大小可根据view的一个方法获取:
view.intrinsicContentSize,获取内容区域。
当试图通过AutoLayout进行布局之后,其实它的大小还是为确定的,但是当给view的内容赋值之后,那么它的内容大小当即会确认并且通过以上参数返回,但是整个view的大小会延迟进行返回。
二,可对自定义view通过intrinsicContentSize进行计算,然后返回其大小。
例如场景:有一九宫格视图,当然是自定义了。 然后通过当前九宫格所显示图片的数量去判断当前view的大小,那么可通过内容进行重算,返回当前内容的大小,获取到当前内容的整体大小,也就可相应的获取整个view的大小,例如:
场景:自定义了一个contentView,然后在ContentView中创建了10个button,但是现在想通过给Button赋值titleText,确定当前Button是否显示(也就是说,如果当前Button没有赋值title,则不显示),并且将显示的区域大小作为contentView的大小。
.h @interface UIContentView : UIView @property (nonatomic,copy)NSArray *texts; @end .m #import "UIContentView.h" @interface UIContentView() @property (nonatomic,strong)NSMutableArray *buttons; @end @implementation UIContentView - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if(self){ self.buttons = [NSMutableArray array]; //创建了5个button [@[@(1),@(2),@(3),@(4),@(5),@(5),@(5),@(5),@(5),@(5),@(5),@(5)] enumerateObjectsUsingBlock:^(NSNumber *nub, NSUInteger idx, BOOL * _Nonnull stop) { UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, idx*80, UIScreen.mainScreen.bounds.size.width, 80)]; button.backgroundColor = [UIColor orangeColor]; [self addSubview:button]; [self.buttons addObject:button]; }]; } return self; } - (void)setTexts:(NSArray *)texts { if(nil != texts){ _texts = texts; [texts enumerateObjectsUsingBlock:^(NSString *text, NSUInteger idx, BOOL * _Nonnull stop) { [self.buttons[idx] setBackgroundColor:self.randomColor]; [self.buttons[idx] setTitle:text forState:UIControlStateNormal]; }]; //重新计算内容区域 [self invalidateIntrinsicContentSize]; } } //返回内容的大小 - (CGSize)intrinsicContentSize { return CGSizeMake(UIScreen.mainScreen.bounds.size.width, 80 * self.texts.count); } - (UIColor *)randomColor { CGFloat hue = arc4random() % 256 / 256.0; //色调随机:0.0 ~ 1.0 CGFloat saturation = (arc4random() % 128 / 256.0) + 0.5; //饱和随机:0.5 ~ 1.0 CGFloat brightness = (arc4random() % 128 / 256.0) + 0.5; //亮度随机:0.5 ~ 1.0 return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; }
以上则通过赋值完texts之后,给Button赋值完title,对视图内容区域进行了重新计算,[self invalidateIntrinsicContentSize]方法会触发intrinsicContentSize方法,让其返回其内容视图的大小,那么外部可以直接怼ContentView进行修改:
UIContentView *contentView = [[UIContentView alloc]initWithFrame:CGRectMake(0, 100, UIScreen.mainScreen.bounds.size.width, 600)]; contentView.clipsToBounds = YES; contentView.backgroundColor = [UIColor blueColor]; [self.view addSubview:contentView]; NSLog(@"%@",NSStringFromCGSize(contentView.intrinsicContentSize)); contentView.texts = @[@"Button-1",@"Button-2",@"Button-3",@"Button-4"]; NSLog(@"%@",NSStringFromCGSize(contentView.intrinsicContentSize)); contentView.frame = CGRectMake(0.0, 100.0, contentView.intrinsicContentSize.width, contentView.intrinsicContentSize.height);
那么如果想在视图内部对其进行自动修改,根据自己的规则。 需要重新sizeToFit方法,切记sizeToFit方法必须调用其父类方法。
- (void)sizeToFit { [super sizeToFit]; self.frame = (CGRect) { self.frame.origin, self.intrinsicContentSize }; }
调用如下:
contentView.texts = @[@"Button-1",@"Button-2",@"Button-3",@"Button-4"]; [contentView sizeToFit];
取消clipsToBounds,不去sizeToFit,看看实际contentView的大小:
此模式一般在自定义视图中进行运用,可根据自己不同的业务需求和规则进行内容重算,这里是根据分配button的title后进行的重算。通过调用该invalidateIntrinsicContentSize方法,告诉系统,视图的intrinsicContentSize值要进行改变了。
一些项目场景:自定义视图,朋友圈布局等。
Add:
给定lable一个宽度和高度,但是label中的内容较少,要获取当前label中内容所占的大小:
label.intrinsicContentSize.width,为当前文字所占的宽度;label.intrinsicContentSize.height为文字所占的高度。