根据内容区域计算视图大小

一,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为文字所占的高度。

Leave a Reply

Required fields are marked *