iOS Autolayout 之 Masonry 使用

Masonry介紹

Masonry是一個輕量級的佈局框架 擁有本身的描述語法 採用更優雅的鏈式語法封裝NSAutoLayout, 簡潔明瞭並具備高可讀性 並且同時支持 iOS 和 Max OS X。使用Masonry可以使用簡單的語法進行Autolayout佈局c++


Masonry經常使用屬性與NSLayoutAttrubute的對照表以下
git

Masonry NSAutoLayout 說明
view.mas_left NSLayoutAttributeLeft 左側
view.mas_top NSLayoutAttributeTop 上側
view.mas_right NSLayoutAttributeRight 右側
view.mas_bottom NSLayoutAttributeBottom 下側
view.mas_leading NSLayoutAttributeLeading 首部
view.mas_trailing NSLayoutAttributeTrailing 尾部
view.mas_width NSLayoutAttributeWidth
view.mas_height NSLayoutAttributeHeight
view.mas_centerX NSLayoutAttributeCenterX 橫向中點
view.mas_centerY NSLayoutAttributeCenterY 縱向中點
view.mas_baseline NSLayoutAttributeBaseline 文本基線

使用Masonry進行Autolayout佈局

Masonry三種Autolayout Compare類型

  • .equalTo 至關於NSLayoutRelationEqual,爲相等
  • .lessThanOrEqualTo至關於 NSLayoutRelationLessThanOrEqual,爲小於或者等於
  • .greaterThanOrEqualTo 至關於 NSLayoutRelationGreaterThanOrEqual,爲大於或等於
// **使用UIView/NSView進行比較**
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            //these two constraints are exactly the same
            make.left.greaterThanOrEqualTo(label.mas_left);
            make.left.right.equalTo(lable);
        }];
        ..
    //2. **直接使用NSNumber進行比較**
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            //width >= 200 && width <= 400
            make.width.greaterThanOrEqualTo(@200);
            make.width.lessThanOrEqualTo(@400)
    }];
    ..
    //3. **使用CGFloat**
    [subGreenView mas_makeConstraints:^(MASConstraintMaker *make) {
            //width >= 200 && width <= 400
            make.width.mas_lessThanOrEqualTo(200);
            make.width.mas_greaterThanOrEqualTo(400);
    }];
複製代碼


兩個同級的view進行約束github

[subGreenView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(subGreenView.mas_left).offset(10);
            make.right.equalTo(subGreenView.mas_right).offset(10);
    }];
複製代碼

left, right, top, bottom, centerX, centerY, leading, trailing, width, height


能夠經過mas_makeConstraints關聯View的left, right, top, bottom, centerX, centerY, leading, trailing, width, height 進行佈局。數組

  1. 使用UIView/NSView進行佈局
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(sv).with.offset(5); //with 不是必要的,只是方便理解
            make.left.equalTo(sv).with.offset(10);
            make.bottom.equalTo(sv).offset(15);
            make.right.equalTo(sv).offset(20);
    }];
複製代碼

或者bash

[subRedView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(subRedView);
            make.left.equalTo(subRedView);
            make.width.equalTo(subRedView);
            make.height.equalTo(subRedView);
    }];
複製代碼
  1. 直接使用NSNumber進行佈局
[subRedView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(@18);
            make.left.equalTo(@16);
            make.width.equalTo(@16);
            make.height.equalTo(@16);
    }];
複製代碼
  1. 直接使用CGFloat進行佈局
[subRedView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerX.mas_equalTo(18);
            make.centerY.mas_equalTo(16);
            make.width.mas_equalTo(16);
            make.height.mas_equalTo(16);
    }];
複製代碼
  1. NSArray
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.height.equalTo(@[view1, view2]);
        make.left.equalTo(@[view1, @100, view3.right]);
    }];
複製代碼

數組有多個不合理的值時,老是獲取最小值來使用.至關於來取最小值.An array of a mixture of any of the previous typesapp

edges, size, center

  • make.edges 至關於同時設置 MASAttributeTop ,MASAttributeLeft , MASAttributeRight , MASAttributeBottom
  • make.size 至關於同時設置 MASAttributeWidth , MASAttributeHeight
  • make.center 至關於同時設置 MASAttributeCenterX, MASAttributeCenterY
[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20));
            make.size.equalTo(superview).sizeOffset(CGSizeMake(100, 50));
            make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10));
    }];
複製代碼

至關於框架

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
            //.insets
            make.top.equalTo(sv).with.offset(5);
            make.left.equalTo(sv).with.offset(10);
            make.bottom.equalTo(sv).with.offset(-15);//使用offset,統一方向,因此這裏是-15
            make.right.equalTo(sv).with.offset(-20);// 統一方向.
            //.size
            make.width.equalTo(sv).offset(100);
            make.height.equalTo(sv).offset(50);
            //.centerOfoffset
            make.centerX.equalTo(sv).offset(-5);
            make.centerY.equalTo(sv).offset(10);
    }];
複製代碼

Masonryz 設置優先級: 優先級有四種方式:

  • .priority 來設定一個明確地優先級的值,是有參數的
  • .priorityHigh 沒有參數,使用默認的MASLayoutPriorityDefaultHigh值
  • .priorityMedium,使用默認的MASLayoutPriorityDefaultMedium值
  • .priorityLow,使用默認的MASLayoutPriorityDefaultLow值.
    與NSAutolayout相似,Masonry會優先實現優先級高的設定,發生衝突時,放棄優先級低的設定.

持有並在其餘時間進行自動佈局的更新


若是要定義須要進行自動佈局更新的約束。好比經過這約束存在來進行動畫效果狀態更新,或者更新刪除約束.
Masonry中有三種方法來更新約束constraints.less

  1. mas_updateConstraints
    使用mas_updateConstraints能夠用來更新視圖的約束,而mas_makeConstraints只能用來建立約束.
    通常是先建立約束,而後在合適的地方使用mas_updateConstraints來更新視圖約束.
[self.likeNumberView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.locationView.mas_bottom)
        .offset(kTopOffsetOfLikeNumberView);
        make.height.mas_equalTo(kHeightOfLikeNumberView);
    }];
複製代碼
  1. mas_remakeConstraints
    mas_updateConstraints只能用來更新約束,可是隻能更新已有約束的值,不能刪除已有約束.
    而使用mas_remakeConstraints的使用方法與mas_updateConstraints相同,可是它在更新視圖以前,會刪除以前全部約束,而後再建立新的約束來更新視圖.
[self.button mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.size.equalTo(self.buttonSize);
            if (topLeft) {
                make.top.and.left.offset(10);
            } else {
                make.bottom.and.right.offset(-10);
            }
    }];
複製代碼
  1. References
    也能夠經過持有一個 MASConstraint類型的約束保持在本地,而後經過installuninstall方法來使用和刪除該約束
    用起來比前兩個複雜,可是靈活性很強,能夠同時刪除和更新約束。
@property (nonatomic, strong) MASConstraint *topConstraint;
..
[subRedView mas_makeConstraints:^(MASConstraintMaker *make) {
_topConstraint = make.top.equalTo(superView.mas_top).with.offset(10);
//這裏是保存了已經設定好的約束
make.left.equalTo(superView.mas_left).with.offset(10);
}];
..
//以後須要取消的時候
[_topConstraint uninstall];
..
//也能夠安裝
[_topConstraint install];
複製代碼

⚠️Masonry 佈局注意事項

  • UILabel 不用設置高度和寬度,設置了高度,字符很容易被截斷
  • 設置的約束有衝突,控制檯會輸出錯誤log,如
2018-03-28 17:50:55.761481+0800 OMI[7256:2846471] [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.
(
"<MASLayoutConstraint:0x1c80bc0e0 SettingsGenderSelectView:0x11be22d30.width == UITableViewCellContentView:0x11be229d0.width>",
"<MASLayoutConstraint:0x1c00adec0 SelectionIndicator:0x11bd160d0.left == OMISingleSelectionView:0x11bd15ed0.left + 20>",
"<MASLayoutConstraint:0x1c00ae220 UILabel:0x11bd16a70.left == OMISelectionIndicator:0x11bd160d0.right + 14>",
"<MASLayoutConstraint:0x1c00ae280 UILabel:0x11bd16a70.right == OMISingleSelectionView:0x11bd15ed0.right + 10>",
"<MASLayoutConstraint:0x1c00af540 SingleSelectionView:0x11bd15ed0.width == OMISettingsGenderSelectView:0x11be22d30.width>",
"<NSLayoutConstraint:0x1c8284d80 UITableViewCellContentView:0x11be229d0.width == 0>"
)
複製代碼

正如輸出中所述,Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger,如今介紹下使用UIViewAlertForUnsatisfiableConstraints的調試方法。ide

在UIViewAlertForUnsatisfiableConstraints添加symbolic breakpoint:佈局

1.打開斷點導航(cmd+7)
2.點擊左下角的+按鈕
3.選擇Add Symbolic Breakpoint
4.在Symbol添加UIViewAlertForUnsatisfiableConstraints
5. 添加po [[UIWindow keyWindow] _autolayoutTrace](OC項目)或expr -l objc++ -O -- [[UIWindow keyWindow] > _autolayoutTrace](Swift項目)

以後你就能夠看到哪裏出錯了:

po [[UIWindow keyWindow] _autolayoutTrace]

UIWindow:0x7f9481c93360
|   •UIView:0x7f9481c9d680
|   |   *UIView:0x7f9481c9d990- AMBIGUOUS LAYOUT for UIView:0x7f9481c9d990.minX{id: 13}, UIView:0x7f9481c9d990.minY{id: 16}
|   |   *_UILayoutGuide:0x7f9481c9e160- AMBIGUOUS LAYOUT for _UILayoutGuide:0x7f9481c9e160.minY{id: 17}
|   |   *_UILayoutGuide:0x7f9481c9ebb0- AMBIGUOUS LAYOUT for _UILayoutGuide:0x7f9481c9ebb0.minY{id: 27}
複製代碼

其中AMBIGUOUS相關的視圖就是約束有問題的。0x7f9481c9d990就是有問題視圖的首地址。能夠快速定位到相關子控件。

其餘調試技巧

固然進一步的調試須要LLDB的命令。好比

打印視圖對象:

(lldb) po 0x7f9481c9d990
<UIView: 0x7f9481c9d990; frame = (0 0; 768 359); autoresize = RM+BM; layer = <CALayer: 0x7fc82d338960>>
複製代碼

改變顏色:

(lldb) expr ((UIView *)0x174197010).backgroundColor = [UIColor redColor]
(UICachedDeviceRGBColor *) $4 = 0x0000000174469cc0
複製代碼

剩下的就是去代碼中找到這個視圖,而後修改其約束了。


延伸資料
Auto Layout Guide
Masonry

相關文章
相關標籤/搜索