Masonry是個(gè)好東西,在當(dāng)前尺寸各異的iOS開發(fā)適配中發(fā)揮著至關(guān)重要的作用,由于項(xiàng)目中Masonry布局用的比較多,對(duì)于UI布局也有了一些自己的理解,經(jīng)常會(huì)有人問道Masonry布局九宮格要怎么布局呢,單行、多行要怎么做到自動(dòng)布局呢,之前用frame布局九宮格需要2層for循環(huán),各種判斷才可以完成一套九宮格布局,那使用Masonry是不是也這么麻煩呢,答案是否定的!下面把Masonry布局單行,多行的代碼貼出來,注釋的很詳細(xì),有需要的同學(xué)可以參考參考,可能對(duì)于Masonry的使用會(huì)有不一樣的理解。
圖片

代碼
#import "ViewController.h"
#import "Masonry.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
? ? [super viewDidLoad];
? ? // Do any additional setup after loading the view, typically from a nib.
? ? //如果需要考慮橫豎屏可以將布局代碼寫在LayoutSubViews這個(gè)方法中
? ? //九宮格布局單行
? ? [selflayoutOneLine];
? ? //九宮格布局多行 其實(shí)跟單行布局差不多,唯一要注意的是要判斷換行的問題? 為了體現(xiàn)差異,把兩種單獨(dú)寫 代碼確實(shí)有大量重復(fù)的
? ? //多行布局是支持單行的
? ? [selflayoutMultiLine];
? ? //分析了代碼可以看出來 多行布局和單行布局其實(shí)沒有什么特殊的地方
? ? //區(qū)別點(diǎn) 1.確定什么時(shí)候換行
? ? //? ? ? 2.確定距離布局區(qū)域頂部的距離多少
? ? //當(dāng)前在真是開發(fā)環(huán)境中還會(huì)存在各種差異,但是只要理解了布局思路,相信不管怎么樣布局都會(huì)游刃有余
}
-(void)layoutOneLine{
? ? //單行布局 不需要考慮換行的問題
? ? CGFloatmarginX =10;? //按鈕距離左邊和右邊的距離
? ? CGFloatmarginY =10;? //按鈕距離布局頂部的距離
? ? CGFloattoTop =50;? //布局區(qū)域距離頂部的距離
? ? CGFloatgap =10;? ? //按鈕與按鈕之間的距離
? ? NSIntegercol =5;? ? //這里只布局5列
? ? NSIntegercount =5;? //這里先設(shè)置布局5個(gè)按鈕
? ? CGFloat viewWidth = self.view.bounds.size.width;? //視圖的寬度
? ? CGFloat viewHeight = self.view.bounds.size.height;? //視圖的高度
? ? CGFloatitemWidth = (viewWidth - marginX *2- (col -1)*gap)/col*1.0f;? //根據(jù)列數(shù) 和 按鈕之間的間距 這些參數(shù)基本可以確定要平鋪的按鈕的寬度
? ? CGFloatheight = itemWidth;? //按鈕的高度可以根據(jù)情況設(shè)定 這里設(shè)置為相等
? ? UIButton*last =nil;? //上一個(gè)按鈕
? ? //準(zhǔn)備工作完畢 既可以開始布局了
? ? for(inti =0; i < count; i++) {
? ? ? ? UIButton*item = [selfbuttonCreat];
? ? ? ? [itemsetTitle:@(i).stringValue forState:UIControlStateNormal];
? ? ? ? [self.viewaddSubview:item];
? ? ? ? //布局
? ? ? ? [itemmas_makeConstraints:^(MASConstraintMaker*make) {
? ? ? ? ? ? //寬高是固定的,前面已經(jīng)算好了
? ? ? ? ? ? make.width.mas_equalTo(itemWidth);
? ? ? ? ? ? make.height.mas_equalTo(height);
? ? ? ? ? ? //topTop距離頂部的距離,單行不用考慮太多,多行,還需要計(jì)算距離頂部的距離
? ? ? ? ? ? make.top.mas_offset(toTop+marginY);
? ? ? ? ? ? if(!last) {? //last為nil 說明是第一個(gè)按鈕
? ? ? ? ? ? ? ? make.left.mas_offset(marginX);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? //第二個(gè)或者后面的按鈕 距離前一個(gè)按鈕右邊的距離都是gap個(gè)單位
? ? ? ? ? ? ? ? make.left.mas_equalTo(last.mas_right).mas_offset(gap);
? ? ? ? ? ? }
? ? ? ? }];
? ? ? ? last = item;
? ? }
}
-(void)layoutMultiLine{
? ? //多行布局 要考慮換行的問題
? ? CGFloatmarginX =10;? //按鈕距離左邊和右邊的距離
? ? CGFloatmarginY =1;? //距離上下邊緣距離
? ? CGFloattoTop =200;? //按鈕距離頂部的距離
? ? CGFloatgapX =10;? ? //左右按鈕之間的距離
? ? CGFloatgapY =10;? ? //上下按鈕之間的距離
? ? NSIntegercol =5;? ? //這里只布局5列
? ? NSIntegercount =13;? //這里先設(shè)置布局任意個(gè)按鈕
? ? CGFloat viewWidth = self.view.bounds.size.width;? //視圖的寬度
? ? CGFloat viewHeight = self.view.bounds.size.height;? //視圖的高度
? ? CGFloatitemWidth = (viewWidth - marginX *2- (col -1)*gapX)/col*1.0f;? //根據(jù)列數(shù) 和 按鈕之間的間距 這些參數(shù)基本可以確定要平鋪的按鈕的寬度
? ? CGFloatitemHeight = itemWidth;? //按鈕的高度可以根據(jù)情況設(shè)定 這里設(shè)置為相等
? ? UIButton*last =nil;? //上一個(gè)按鈕
? ? //準(zhǔn)備工作完畢 既可以開始布局了
? ? for(inti =0; i < count; i++) {
? ? ? ? UIButton*item = [selfbuttonCreat];
? ? ? ? [itemsetTitle:@(i).stringValue forState:UIControlStateNormal];
? ? ? ? [self.viewaddSubview:item];
? ? ? ? //布局
? ? ? ? [itemmas_makeConstraints:^(MASConstraintMaker*make) {
? ? ? ? ? ? //寬高是固定的,前面已經(jīng)算好了
? ? ? ? ? ? make.width.mas_equalTo(itemWidth);
? ? ? ? ? ? make.height.mas_equalTo(itemHeight);
? ? ? ? ? ? //topTop距離頂部的距離,單行不用考慮太多,多行,還需要計(jì)算距離頂部的距離
? ? ? ? ? ? //計(jì)算距離頂部的距離 --- 根據(jù)換行
? ? ? ? ? ? CGFloattop = toTop + marginY + (i/col)*(itemHeight+gapY);
? ? ? ? ? ? make.top.mas_offset(top);
? ? ? ? ? ? if (!last || (i%col) == 0) {? //last為nil? 或者(i%col) == 0 說明換行了 每行的第一個(gè)確定它距離左邊邊緣的距離
? ? ? ? ? ? ? ? make.left.mas_offset(marginX);
? ? ? ? ? ? }else{
? ? ? ? ? ? ? ? //第二個(gè)或者后面的按鈕 距離前一個(gè)按鈕右邊的距離都是gap個(gè)單位
? ? ? ? ? ? ? ? make.left.mas_equalTo(last.mas_right).mas_offset(gapX);
? ? ? ? ? ? }
? ? ? ? }];
? ? ? ? last = item;
? ? }
}
#pragma mark - Private
-(UIButton*)buttonCreat{
? ? UIButton*item = [[UIButtonalloc]init];
? ? item.backgroundColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0f];
? ? item.titleLabel.font = [UIFont systemFontOfSize:16];
? ? [itemsetTitleColor:[UIColor redColor] forState:UIControlStateNormal];
? ? returnitem;
}
@end
如上,代碼中的注釋已經(jīng)很詳細(xì)了,相信看到這里的同學(xué)都已經(jīng)明白了布局原理,這里強(qiáng)調(diào)下最后總結(jié)的幾句話:
分析了代碼可以看出來 多行布局和單行布局其實(shí)沒有什么特殊的地方
區(qū)別點(diǎn) 1.確定什么時(shí)候換行
2.確定距離布局區(qū)域頂部的距離多少
當(dāng)前在真是開發(fā)環(huán)境中還會(huì)存在各種差異,但是只要理解了布局思路,相信不管怎么樣布局都會(huì)游刃有余