AutoLayout和Masonry兩種方式實現自動佈局的內容包裹和檢視均分

Deft_MKJing宓珂璟發表於2017-05-10

前言

這兩種方式分別代表了兩種人,一種快速佈局,直觀,但是很多人認為很難維護,後者純程式碼佈局,老一派的人用起來都說好,反正一說起來就打起來了,一個雖然快,但是難以維護啊,一個雖然寫起來很多,但是維護起來簡單啊,巴拉巴拉的,我個人覺得,適配的話最好能深刻理解AutoLayout,Apple特有的東西,理解下也好,有了直觀的理解之後,你再用Masonry就非常的簡單了,個人觀點而已,不喜勿噴,主要之前參與的App有兩個是純AutoLayout,沒錯,是純的,而且是多人開發,玩起來一樣沒問題,現在對這些東西理解的還算可以,報錯什麼的也能及時搞定了,廢話不多了,記錄了兩個最常用的知識點

示例圖

這裡寫圖片描述

分析

上面兩個圖是程式碼完成,下面兩個是自動佈局,現在簡單看下區別和實現

AutoLayout實現包裹和均分

這裡寫圖片描述



以下是均分的約束,這裡看不懂的就可以去面壁了,去翻翻我之前的幾篇部落格就知道了,基本上就是紅色新增上,左,下的約束,然後黃色新增上,右,下,左,再來個等寬,搞定
AutoLayout和Masonry兩種方式實現自動佈局的內容包裹和檢視均分



以下是子檢視內容撐開父視(父檢視frame不定)的約束,首先你的灰色底部父檢視我只給定了X和Y的座標,size不定,然後內部黑色填充上,左,下,然後給Size,藍色填充上,右,下,左邊,然後給size

AutoLayout和Masonry兩種方式實現自動佈局的內容包裹和檢視均分



注意:這裡看起來簡單,如果你做內容包裹,你像我這麼做這裡有個坑,其實這個就是反面教材,這裡其實只處理了一種等高的情況,如果你的左邊和右邊高度不一樣,系統會給出你警告,讓你再自己看看這不合理的約束,類似於這種錯誤,其實就是你的約束不是完美的,有衝突了,這個如果你用程式碼寫,你就很難最終和找到了,但是你用Autolayout,你根本不需要Run,在拉約束的時候就看到了,這也算是個優點吧,下面再看看不等高的程式碼實現

2017-05-10 15:15:41.717981+0800 SystemTime[55019:5807911] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x600000085a00 UIView:0x7f8bbf70c350.height == 100>",
    "<NSLayoutConstraint:0x600000085af0 UIView:0x7f8bbf70c6f0.height == 70>",
    "<NSLayoutConstraint:0x600000085b40 UIView:0x7f8bbf70c1b0.bottom == UIView:0x7f8bbf70c6f0.bottom + 10>",
    "<NSLayoutConstraint:0x600000085b90 UIView:0x7f8bbf70c6f0.top == UIView:0x7f8bbf70c1b0.top + 10>",
    "<NSLayoutConstraint:0x600000085c80 UIView:0x7f8bbf70c350.top == UIView:0x7f8bbf70c1b0.top + 10>",
    "<NSLayoutConstraint:0x600000085d20 UIView:0x7f8bbf70c1b0.bottom == UIView:0x7f8bbf70c350.bottom + 10>"
)


Masonry實現包裹和均分

這裡寫圖片描述


很明顯能看出,上面是均分,下面是包裹,直接看程式碼吧

// 程式碼實現內容包裹和均分
@property (nonatomic,strong) UIView *backView;

// 均分父檢視(父檢視X,Y,W,H都已知,代表frame已定)
@property (nonatomic,strong) UIView *averageView;
@property (nonatomic,strong) UIView *averageLeftView;
@property (nonatomic,strong) UIView *averageRightView;

// 用子檢視的內容來填充賦值父檢視的frame 父檢視已知X,Y,height和width都是由子檢視來填充
@property (nonatomic,strong) UIView *fillBackView;
@property (nonatomic,strong) UIView *fillLeftView;
@property (nonatomic,strong) UIView *fillMiddleView;
@property (nonatomic,strong) UIView *fillRightView;

self.backView  = [[UIView alloc] init];
    self.backView.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.7];
    [self.view addSubview:self.backView];
    [self.backView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.equalTo(self.view);
        make.height.equalTo(@([UIScreen mainScreen].bounds.size.height/2.5));
    }];


    self.averageView = [[UIView alloc] init];
    self.averageView.backgroundColor = [UIColor blackColor];
    [self.backView addSubview:self.averageView];
    [self.averageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.right.equalTo(self.backView);
        make.height.equalTo(self.backView.mas_height).multipliedBy(0.5);
    }];


    self.averageLeftView = [[UIView alloc] init];
    self.averageLeftView.backgroundColor = [UIColor blueColor];
    [self.averageView addSubview:self.averageLeftView];
    [self.averageLeftView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.top.equalTo(self.averageView).with.offset(10);
        make.bottom.equalTo(self.averageView).with.offset(-10);
    }];

    self.averageRightView = [[UIView alloc] init];
    self.averageRightView.backgroundColor = [UIColor greenColor];
    [self.averageView addSubview:self.averageRightView];
    [self.averageRightView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.bottom.equalTo(self.averageView).with.offset(-10);
        make.top.equalTo(self.averageView).with.offset(10);
        make.left.equalTo(self.averageLeftView.mas_right).with.offset(10);
        make.width.equalTo(self.averageLeftView.mas_width);
    }];


    self.fillBackView = [[UIView alloc] init];
    self.fillBackView.backgroundColor = [UIColor purpleColor];
    [self.backView addSubview:self.fillBackView];
    // 包裹內容
    [self.fillBackView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.averageView.mas_bottom).with.offset(30);
        make.centerX.equalTo(self.backView);
    }];

    // 子檢視填充
    self.fillLeftView = [[UIView alloc]  init];
    self.fillLeftView.backgroundColor = [UIColor redColor];
    [self.fillBackView addSubview:self.fillLeftView];

    [self.fillLeftView mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.top.equalTo(self.fillBackView).with.offset(10);
        make.centerY.equalTo(self.fillBackView);
        make.left.equalTo(self.fillBackView).with.offset(10);
//        make.bottom.equalTo(self.fillBackView).with.offset(-10);
        make.size.mas_equalTo(CGSizeMake(80, 60));

    }];

    self.fillMiddleView = [[UIView alloc]  init];
    self.fillMiddleView.backgroundColor = [UIColor orangeColor];
    [self.fillBackView addSubview:self.fillMiddleView];

    [self.fillMiddleView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.fillLeftView.mas_right).with.offset(10);
        make.centerY.equalTo(self.fillBackView);
//        make.top.equalTo(self.fillBackView).with.offset(10);
//        make.bottom.equalTo(self.fillBackView).with.offset(-10);
        make.size.mas_equalTo(CGSizeMake(30, 60));

    }];


    self.fillRightView = [[UIView alloc]  init];
    self.fillRightView.backgroundColor = [UIColor blueColor];
    [self.fillBackView addSubview:self.fillRightView];
    [self.fillRightView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.right.bottom.equalTo(self.fillBackView).with.offset(-10);
        make.top.equalTo(self.fillBackView).with.offset(10);
        make.left.equalTo(self.fillMiddleView.mas_right).with.offset(10);
        make.size.mas_equalTo(CGSizeMake(200, 100));
    }];



這裡我之前也是和上面的AutoLayout一樣是等高的示例,就是那幾句注掉的程式碼,但是為了突出剛才的約束嚴格意義上來講是有問題的,因此這裡給了一個不等高的特殊情況,程式碼很少,隨意感受下效果,最後的點選事件

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.fillRightView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(@10);
    }];

    [self.averageRightView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.averageLeftView.mas_right).with.offset(300);
    }];


    [UIView animateWithDuration:2.0f animations:^{
        [self.fillBackView layoutIfNeeded];
        [self.averageView layoutIfNeeded];
        self.backView.hidden = YES;
    }];
}


Demo地址
Demo裡面還有一個另外的東西,由於都只是小知識點,就放在一起了,一個對iOS設計倒數計時的思路和遇到的坑
cell倒數計時問題遇到的坑

相關文章