欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Masonry的约束布局,scrollView与cell的自动适配

程序员文章站 2022-06-08 16:31:01
...

公司项目使用Masonry已经很久了,上一篇中介绍了约束的原生api和Masonry的一些基础用法,还对Label等控件的自带宽高问题进行了说明。今天我写一篇实用的关于scrollView的约束布局与cell的自动适配用法。

gitHub:https://github.com/yangqingren/LBMasonry.git

我们在使用约束布局的时候,子view通常可以决定自己的size,父view是可以不参与自子view的size布局的。比如:


@interface LBView ()
@property (nonatomic,strong)UIView *subView;
@end
@implementation LBView

- (instancetype)init {
    if (self = [super init]) {

        [self addSubview:self.subView];
        [self.subView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.left.right.mas_equalTo(self);  // make. edges
            make.height.mas_equalTo(100);
            make.bottom.mas_equalTo(self.mas_bottom);
        }];
    }
    return self;
}

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.lbView];
    [self.view addSubview:self.lbLabel];

    // self.lbView的size已经内部设置,所以不需要再次设置
    [self.lbView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.offset(50);
        make.right.offset(-50);
    }];

    // 验证self.lbView已经存在size
    [self.lbLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.right.mas_equalTo(self.lbView);
        make.top.mas_equalTo(self.lbView.mas_bottom).offset(10);
    }];

    // Do any additional setup after loading the view, typically from a nib.
}

// 注:Masonry的block没有被self(即调用的view)持有,所以并不需要进行weakSelf

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

// 我们自己做组件的时候也可以参考一下,做到这种效果

以上面的常见用法,引出了我在约束布局之路上的两个特殊例子:

  • scrollView的约束布局

使用scrollView的时候不需要去计算其contentSize,由其子view来进行约束设置。如果你还在使用scrollView的时候设置其contentSize,直接的话的讲,就是在写死布局。
如以上例子,当约束在水平(竖直)方向是满足两个条件,即足够完成布局,比如left+width(或者left+right或者right+width)。
但是当view的父类是scrollView时,则水平和竖直方向上都需要设置满3个条件,才能完成布局,例如:


- (UIScrollView *)scrollView {
    if (!_scrollView) {
    // 不需要设置contentSize
        _scrollView = [[UIScrollView alloc] init];
    }
    return _scrollView;
}
- (void)viewDidLoad {
    [super viewDidLoad];

    [self.view addSubview:self.scrollView];

    [self.scrollView addSubview:self.view1];
    [self.scrollView addSubview:self.view2];

    [self.scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(self.view);
    }];
    // 加上width约束scrollView的contentSize的width,让scrollView在水平方向上能够撑开
    [self.view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.mas_equalTo(self.scrollView);
        make.height.mas_equalTo(500);
        make.width.mas_equalTo(self.view.bounds.size.width);
    }];
    // 加上bottom连接scrollView的底部,加上两个view的高,让scrollView在竖直方向上能够撑开
    [self.view2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.view1.mas_bottom).offset(10);
        make.left.right.mas_equalTo(self.scrollView);
        make.height.mas_equalTo(500);
        make.bottom.mas_equalTo(self.scrollView.mas_bottom).offset(-10);
    }];

    // Do any additional setup after loading the view, typically from a nib.
}

约束布局不需要去计算scrollView的contentSize,让代码更加易于维护。

  • cell的自动算高

凡是能够使用scrollView布局的页面,tableView都能完成,比如一些表单页面,用tableView做就很方便数据的填充:

Masonry的约束布局,scrollView与cell的自动适配

在做表单的时候,需要对不同cell进行不同的高度设置,有了cell的自动算高,这项工作就很轻松了。

首先需要给表单设置一个大约cell高度,以及设置cell的自动布局:

_tableView.estimatedRowHeight = 200;
_tableView.rowHeight = UITableViewAutomaticDimension;

// 或者是个别cell不需要自动算高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (0 == indexPath.section && 0 == indexPath.row) {
        return 150;
    }
    return UITableViewAutomaticDimension;
}

之后在cell里面对其的高度进行有效设置(水平方向不需要设置,cell的宽度默认为tableView的宽度):


- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
- 
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        [self addSubview:self.textField];

        // 满足竖直方向上能够表达出cell的size的约束
        [self.textField mas_makeConstraints:^(MASConstraintMaker *make) {
            make.height.mas_equalTo(90);
            make.edges.insets(UIEdgeInsetsMake(5, 15, 5, 15));
        }];
    }
    return self;
}

这样building出来的表单就是可以是自动算高的了。

至此,约束布局之路基本完成,可能在之后还会写一些关于约束的更特别的用法。

当然,对于表单结构,也可设置其压缩拉伸优先级达到效果:

    // 禁止拉伸优先级
    [self.numLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
    // 禁止压缩优先级
    [self.numLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];

gitHub:https://github.com/yangqingren/LBMasonry.git

end