iOS經常使用第三方庫之Masonry

1、前言git

  關於蘋果的佈局一直是我比較糾結的問題,是寫代碼來控制佈局,仍是使用storyboard來控制佈局呢?之前我我的開發的時候不多使用代碼去寫約束,由於太麻煩了。因此最終選擇的都是AutoLayout進行佈局,而後拖線設置約束。不過好多公司進行iOS開發的時候都會去動態的修改約束,並且有的會使用約束去建立一些動畫,因此不太去用storyboard進行開發(還有就是使用storyboard幾我的合做的時候比較麻煩)。反倒更多的是寫代碼開發看起來更加的高效。因此好多開發者都開始去使用Masonry。它是一個封裝的第三方類庫,做用就是來簡化開發者寫佈局約束。github

2、「安裝」Masonryapp

  由於它是一個第三方的類庫,咱們能夠從這裏下載,而後解壓將Masonry那個文件夾拖入本身的項目文件夾下便可。less

3、開始使用Masonryide

  咱們在使用它的時候,最好在AppDelegate.m的佈局

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;

方法中去自定義加載本身的控制器。例如我寫的時候就是這樣:動畫

複製代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    return YES;
}
複製代碼

直接加載的我本身寫的ViewController。(建議把系統自帶的Main.stoaryboard刪除掉,若是運行報錯本身修改,問題不大)。ui

先來一個不用Masonry寫的最簡單的佈局:(目的是在視圖中添加一個視圖)this

複製代碼
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title  = @"Basic View";
    UIView *view1 = [[UIView alloc] init];
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view1.backgroundColor = [UIColor greenColor];
    [superview addSubview:view1];
    
    UIEdgeInsets padding = UIEdgeInsetsMake(74, 10, 10, 10);
    
    [superview addConstraints:@[
                                
                                //view1 constraints
                                [NSLayoutConstraint constraintWithItem:view1
                                                             attribute:NSLayoutAttributeTop
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:superview
                                                             attribute:NSLayoutAttributeTop
                                                            multiplier:1.0
                                                              constant:padding.top],
                                
                                [NSLayoutConstraint constraintWithItem:view1
                                                             attribute:NSLayoutAttributeLeft
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:superview
                                                             attribute:NSLayoutAttributeLeft
                                                            multiplier:1.0
                                                              constant:padding.left],
                                
                                [NSLayoutConstraint constraintWithItem:view1
                                                             attribute:NSLayoutAttributeBottom
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:superview
                                                             attribute:NSLayoutAttributeBottom
                                                            multiplier:1.0
                                                              constant:-padding.bottom],
                                
                                [NSLayoutConstraint constraintWithItem:view1
                                                             attribute:NSLayoutAttributeRight
                                                             relatedBy:NSLayoutRelationEqual
                                                                toItem:superview
                                                             attribute:NSLayoutAttributeRight
                                                            multiplier:1
                                                              constant:-padding.right],
                                
                                ]];

}
複製代碼

運行效果以下:atom

這就是咱們用系統的NSLayoutConstraint寫的一個view,而後將這個view加載到根view中。如今咱們用Masonry來實現和上邊同樣的效果:

第一步、導入類庫

#import "Masonry.h"

而後修改代碼以下:

複製代碼
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title  = @"Basic View";
    UIView *superview = self.view;
    
    UIView *view1 = [[UIView alloc] init];
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view1.backgroundColor = [UIColor greenColor];
    [superview addSubview:view1];
    
    UIEdgeInsets padding = UIEdgeInsetsMake(74, 10, 10, 10);
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(superview.mas_top).offset(padding.top);
        make.left.equalTo(superview.mas_left).offset(padding.left);
        make.bottom.equalTo(superview.mas_bottom).offset(-padding.bottom);
        make.right.equalTo(superview.mas_right).offset(-padding.right);
    }];
}
複製代碼

上面的效果和原來用NSLayoutConstraint實現的效果是同樣的,因此就再也不貼圖。

咱們能夠看到,咱們使用的一個mas_makConstrints塊來進行約束設置。view1指代的就是要添加約束的view(也能夠是button,label等等)。而後make的top,left,bottom,right就至關於view1的上下左右,而後equalTo()括號內的就是相對的view,而後offset是偏移量。

還能夠更簡單的實現:

複製代碼
- (void)viewDidLoad {
    [super viewDidLoad];
    self.title  = @"Basic View";
    UIView *superview = self.view;
    
    UIView *view1 = [[UIView alloc] init];
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view1.backgroundColor = [UIColor greenColor];
    [superview addSubview:view1];
    
    UIEdgeInsets padding = UIEdgeInsetsMake(74, 10, 10, 10);
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(superview).with.insets(padding);
    }];
//    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
//        make.top.equalTo(superview.mas_top).offset(padding.top);
//        make.left.equalTo(superview.mas_left).offset(padding.left);
//        make.bottom.equalTo(superview.mas_bottom).offset(-padding.bottom);
//        make.right.equalTo(superview.mas_right).offset(-padding.right);
//    }];
}
複製代碼

以上的三種方式都是實現上邊圖種的效果。

MASViewAttribute NSLayoutAttribute
view.mas_left NSLayoutAttributeLeft
view.mas_right NSLayoutAttributeRight
view.mas_top NSLayoutAttributeTop
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

 

以上的屬性對應相應的NSLayoutAttribute。

下面就來看它的使用吧。(先上效果圖,而後再上代碼)

使用1、簡單的三個視圖的佈局

這個時我直接自定義了一個ZGBasicView視圖,而後添加到了ViewController中。

關鍵代碼以下:

複製代碼
//
//  ZGBasicView.m
//  MasonryDemo
//
//  Created by zhanggui on 15/10/26.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "ZGBasicView.h"
#import "View+MASShorthandAdditions.h"
@implementation ZGBasicView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/
- (id)init {
    self = [super init];
    if (!self) {
        return nil;
    }
//        self.translatesAutoresizingMaskIntoConstraints = YES;
        //紅色視圖
        UIView *redView = [UIView new];
        redView.backgroundColor = [UIColor redColor];
        redView.layer.borderColor = [UIColor blackColor].CGColor;
        redView.layer.borderWidth = 2;
        [self addSubview:redView];
        //綠色視圖
        UIView *greenView = [[UIView alloc] init];
        greenView.backgroundColor = [UIColor greenColor];
        greenView.layer.borderColor = [UIColor blackColor].CGColor;
        greenView.layer.borderWidth = 2;
        [self addSubview:greenView];
     
        //藍色視圖
        UIView *blueView = [[UIView alloc] init];
        blueView.backgroundColor = [UIColor blueColor];
        blueView.layer.borderWidth = 2;
        blueView.layer.borderColor = [UIColor blackColor].CGColor;
        
        [self addSubview:blueView];
        
        
        int padding = 10;
        UIView *superview = self;
      
        
        //with is semantic and option
        [redView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(superview.mas_top).offset(padding); //with with
            make.left.equalTo(greenView.mas_right).offset(padding); //without with
            make.bottom.equalTo(blueView.mas_top).offset(-padding);
            make.right.equalTo(superview.mas_right).offset(-padding);
            make.width.equalTo(greenView.mas_width);
            
            make.height.equalTo(@[greenView, blueView]); //can pass array of views
        }];
        [greenView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(superview.mas_top).offset(padding);
            make.left.equalTo(superview.mas_left).offset(padding);
            make.bottom.equalTo(blueView.mas_top).offset(-padding);
            make.right.equalTo(redView.mas_left).offset(-padding);
            make.width.equalTo(redView.mas_width);
            
            make.height.equalTo(redView.mas_height);
//            make.height.equalTo(blueView.mas_height);
        }];
        [blueView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(greenView.mas_bottom).offset(padding);
            make.left.equalTo(superview.mas_left).offset(padding);
            make.bottom.equalTo(superview.mas_bottom).offset(-padding);
            make.right.equalTo(superview.mas_right).offset(-padding);
            make.height.equalTo(greenView.mas_height); //can pass array of attributes
        }];
    return self;
}
@end
複製代碼

三個視圖之間的關係。

場景2、更新視圖

效果圖以下:

實現代碼以下:(這裏也是自定義了一個View,而後將這個view加入到了根視圖中)

複製代碼
//
//  UpdateConstraintsView.m
//  MasonryDemo
//
//  Created by zhanggui on 15/10/26.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "UpdateConstraintsView.h"
#import "Masonry.h"

@interface UpdateConstraintsView ()

@property (nonatomic,strong)UIButton *myButton;
@property (nonatomic,assign)CGSize buttonSize;
@end
@implementation UpdateConstraintsView

- (id)init {
    self = [super init];
    if (self) {
        self.myButton = [UIButton buttonWithType:UIButtonTypeSystem];
        [self.myButton setTitle:@"更新約束" forState:UIControlStateNormal];
        self.myButton.layer.borderColor = [UIColor blackColor].CGColor;
        self.myButton.layer.borderWidth = 2;
        [self.myButton addTarget:self action:@selector(changeAction:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.myButton];
        self.buttonSize = CGSizeMake(100, 100);
    }
    return self;
}
/**
 Returns whether the receiver depends on the constraint-based layout system.
 YES if the view must be in a window using constraint-based layout to function properly, NO otherwise.
 */
+ (BOOL)requiresConstraintBasedLayout {
    return YES;
}
/**
 Updates constraints for the view.
 Custom views that set up constraints themselves should do so by overriding this method. When your custom view notes that a change has been made to the view that invalidates one of its constraints, it should immediately remove that constraint, and then call setNeedsUpdateConstraints to note that constraints need to be updated. Before layout is performed, your implementation of updateConstraints will be invoked, allowing you to verify that all necessary constraints for your content are in place at a time when your custom view’s properties are not changing.
 You must not invalidate any constraints as part of your constraint update phase. You also must not invoke a layout or drawing phase as part of constraint updating.
 Important:Important
 Call [super updateConstraints] as the final step in your implementation.
 蘋果推薦在這個方法裏面添加或者更新約束
 */
- (void)updateConstraints {
    [self.myButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();  //設置優先級以及width
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        //設置myButton的大小小於等於自身view的大小
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];
    [super updateConstraints];
}
- (void)changeAction:(UIButton *)button {
    self.buttonSize = CGSizeMake(self.buttonSize.width*1.2, self.buttonSize.height*1.2);

    //告訴約束他們須要更新
    [self setNeedsUpdateConstraints];
    //update constraints now
    [self updateConstraintsIfNeeded];
    //設置更新大小動畫
    [UIView animateWithDuration:0.5 animations:^{
        /**
         Lays out the subviews immediately.
         Use this method to force the layout of subviews before drawing. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root.
         */
        [self layoutIfNeeded];
    }];
}
@end
複製代碼

這裏主要使用了mas_updateConstraints:方法

場景3、讓約束復原

實現代碼以下:

複製代碼
//
//  ReBackConstraintsView.m
//  MasonryDemo
//能夠恢復原來的約束
//  Created by zhanggui on 15/10/26.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "ReBackConstraintsView.h"
#import "Masonry.h"
@interface ReBackConstraintsView ()
@property (nonatomic,strong)UIButton *myButton;
@property (nonatomic,assign)BOOL isAtTop;

@end

@implementation ReBackConstraintsView

- (id)init {
    self = [super init];
    if (self) {
        self.myButton = [UIButton buttonWithType:UIButtonTypeSystem];;
        [self.myButton setTitle:@"Move Me!" forState:UIControlStateNormal];
        self.myButton.layer.borderColor = UIColor.greenColor.CGColor;
        self.myButton.layer.borderWidth = 3;
        
        [self.myButton addTarget:self action:@selector(moveAction:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.myButton];
        
        self.isAtTop = YES;
        

    }
    return self;
}
+ (BOOL)requiresConstraintBasedLayout {
    return YES;
}
- (void)updateConstraints {
    [self.myButton mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.width.equalTo(@(100));
        make.height.equalTo(@(100));
        if (self.isAtTop) {
            make.left.equalTo(self.mas_left).offset(10);
            make.top.equalTo(self.mas_top).offset(10);
        }else {
            make.bottom.equalTo(self.mas_bottom).offset(-10);
            make.right.equalTo(self.mas_right).offset(-10);
            
            
            
            
        }

    }];
    
    [super updateConstraints];
}
- (void)moveAction:(UIButton *)myButton {
    self.isAtTop = !self.isAtTop;
    //告訴約束他們須要更新
    [self setNeedsUpdateConstraints];
    //馬上更新視圖約束
    [self updateConstraintsIfNeeded];
    [UIView animateWithDuration:0.3 animations:^{
        [self layoutIfNeeded];
    }];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end
複製代碼

這裏主要使用了mas_remakeConstraints:方法。

場景4、兩個視圖的嵌套

實現代碼:

複製代碼
//
//  NestConstraintsView.m
//  MasonryDemo
//
//  Created by zhanggui on 15/10/26.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "NestConstraintsView.h"
#import "Masonry.h"
@implementation NestConstraintsView

- (id)init {
    self = [super init];
    if (self) {
        UIView *bigView = [[UIView alloc] init];
        bigView.backgroundColor = [UIColor blackColor];
        [self addSubview:bigView];
        
        UIView *smallView = [[UIView alloc] init];
        smallView.backgroundColor = [UIColor redColor];
        [self addSubview:smallView];
        
        [bigView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(self).offset(20);
            make.left.equalTo(self).offset(20);
            make.bottom.equalTo(self).offset(-20);
            make.right.equalTo(self).offset(-20);
        }];
        [smallView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(bigView.mas_top).offset(40);
            make.left.equalTo(bigView.mas_left).offset(40);
            make.bottom.equalTo(bigView.mas_bottom).offset(-40);
            make.right.equalTo(bigView.mas_right).offset(-40);
        }];
    }
    return self;
}
@end
複製代碼

這裏和第一個場景同樣,都是最基本的實現約束的添加,只不過相對參照物不一樣。

場景5、多個view一塊兒佈局(以組爲單位佈局)

效果:

實現代碼:

複製代碼
//
//  GroupButtonView.m
//  MasonryDemo
//
//  Created by zhanggui on 15/10/26.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "GroupButtonView.h"
#import "Masonry.h"
@implementation GroupButtonView

- (instancetype)init {
    self  = [super init];
    if (self) {
        NSArray *strArr = @[@"10",@"20",@"50",@"100",@"200",@"300"];
        NSMutableArray *mutableArr = [[NSMutableArray alloc] initWithCapacity:6];
        for (int i=0; i<3; i++) {
            UIButton *button = [[UIButton alloc] init];
            [button setTitle:strArr[i] forState:UIControlStateNormal];
            [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            button.layer.borderColor = [UIColor blackColor].CGColor;
            [button addTarget:self action:@selector(show:) forControlEvents:UIControlEventTouchUpInside];
            button.layer.borderWidth = 2;
            [self addSubview:button];
            [mutableArr addObject:button];
        }

                [mutableArr mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:20 leadSpacing:20 tailSpacing:20];
                [mutableArr mas_makeConstraints:^(MASConstraintMaker *make) {
                    make.top.equalTo(@120);
                    make.height.equalTo(@75);
                }];
        /**
         *  -----------------------
         */
        NSMutableArray *marr = [NSMutableArray new];
        for (int i=3; i<6; i++) {
            UIButton *button = [[UIButton alloc] init];
            [button setTitle:strArr[i] forState:UIControlStateNormal];
            [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            button.layer.borderColor = [UIColor blackColor].CGColor;
            [button addTarget:self action:@selector(show:) forControlEvents:UIControlEventTouchUpInside];
            button.layer.borderWidth = 2;
            [self addSubview:button];
            [marr addObject:button];
        }
        
        [marr mas_distributeViewsAlongAxis:MASAxisTypeHorizontal withFixedSpacing:20 leadSpacing:20 tailSpacing:20];
        [marr mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(@200);
            make.height.equalTo(@75);
        }];

        
        }
    return self;
}
- (void)show:(UIButton *)button
{
    NSLog(@"%@",button.titleLabel.text);
}
@end
複製代碼

在這裏,咱們主要就是用到了mas_distributeViewsAlongAxis:...這個方法,來萬曾一組視圖的佈局。

場景6、本身寫的一個簡單的登陸界面

效果以下:

代碼以下:

複製代碼
//
//  ViewController.m
//  MasonryDemo
//
//  Created by zhanggui on 15/10/8.
//  Copyright © 2015年 zhanggui. All rights reserved.
//

#import "ViewController.h"
#import "Masonry.h"
#import "ZGBasicView.h"
#import "UpdateConstraintsView.h"
#import "ReBackConstraintsView.h"
#import "NestConstraintsView.h"
#import "GroupButtonView.h"
#import "LoginView.h"
#import "ArrayView.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title  = @"登陸";
    
    [self loginView];
//    [self addArrayView];


}
- (void)loginView {
    LoginView *loginView = [[LoginView alloc] init];
    self.view = loginView;
//    loginView.frame = self.view.frame;
//    [self.view addSubview:loginView];
}
- (void)addArrayView {
    ArrayView *arrView = [[ArrayView alloc] init];
    self.view = arrView;
}
- (void)groupButtonView {
    GroupButtonView *nestView = [[GroupButtonView alloc] init];
    nestView.frame = self.view.frame;
//    self.view = nestView;
    [self.view addSubview:nestView];
}
- (void)nestConstraintsView {
    NestConstraintsView *nestView = [[NestConstraintsView alloc] init];
    self.view = nestView;

}
- (void)reBackConstraints {
    ReBackConstraintsView *rebackView = [[ReBackConstraintsView alloc] init];
    self.view = rebackView;
}
- (void)updateConstraintsView {
    UpdateConstraintsView *updateView = [[UpdateConstraintsView alloc] init];
    self.view = updateView;
}
- (void)simpleView {
    ZGBasicView *basicView = [[ZGBasicView alloc] init];
//    [self.view addSubview:basicView];
    self.view = basicView;
}
- (void)firstSimpleView {
    UIView *superview = self.view;
    UIView *view1 = [[UIView alloc] init];
    view1.translatesAutoresizingMaskIntoConstraints = NO;
    view1.backgroundColor = [UIColor greenColor];
    [superview addSubview:view1];
    
    UIEdgeInsets padding = UIEdgeInsetsMake(74, 10, 10, 10);
    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(superview).with.insets(padding);
    }];
    //    [view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    //        make.top.equalTo(superview.mas_top).offset(padding.top);
    //        make.left.equalTo(superview.mas_left).offset(padding.left);
    //        make.bottom.equalTo(superview.mas_bottom).offset(-padding.bottom);
    //        make.right.equalTo(superview.mas_right).offset(-padding.right);
    //    }];
}
@end
複製代碼

你們能夠簡單的看一下,寫的比較簡單,應該很容易理解的。(橫屏的距離上邊的高度沒有處理太好,將就着看吧)

簡單就介紹這麼多了。

附:

  一、源碼下載地址:http://pan.baidu.com/s/1o6083G2

  二、Masonry Git地址:https://github.com/SnapKit/Masonry

相關文章
相關標籤/搜索