布局:

   1. 放在哪  坐标  CGPoint(x, y)


   2. 有多大  尺寸  CGSize(width, height)




布局方式:

   1.绝对布局(FrameLayout)也称 坐标布局


   2.自动布局(AutoLayout)



FrameLayout(绝对布局)

     方式:


      一种方式可以直接使用frame来定义坐标和宽高,


      一种方式是 先使用bounds 属性赋值确定尺寸(宽, 高),然后使用center确定坐标(x, y)      ① view.frame = [位置,尺寸];


      ② view.bounds = CGRect


         view.center = (x, y) 


     优点:直观、简单


     缺点:屏幕适配难度大,需要复杂的几何运算


     基于:基于frame布局



AutoLayout(自动布局)

   方式:自动布局有很多方式,可以使用iOS系统本身的(自带的API太繁杂)、也可以使用github上的第三方库(Masonry)


   优点:解决了不同分辨率和屏幕尺寸下view的适配问题,另外也简化了旋转时view的位置的定义


   基于:基于约束(Constraint)布局



自动布局AutoLayout简介:

自动布局是一种基于约束的,描述性的布局系统,使用约束条件来描述布局,使用AutoLayout布局就和坐标没有任何关系了,


view的位置会根据约束条件自动计算出frame,最大好处是一举解决了不同分辨率和屏幕尺寸下view的适配问题,另外也简化了旋转时view的位置的定义。


自动布局是基于约束的,和坐标没有半点关系。系统将根据不同的约束来自动计算控件的具体位置,最终也将使用绝对布局!只不过暴露给开发者的是一些约束


如果使用自动布局而不加任何约束,那么系统会自动添加约束



自动布局的使用方式:


1. 可以在XIB或storybord上直接在界面上添加约束


右下角一组四个按钮:Stack、Align对齐、Pin定位、Resolve Auto Layout Issues



Update Frames


Add 1 Constraint



2. 也可以使用纯代码来添加约束



对于布局技术趋势: 以后的趋势将会逐渐使用 自动布局AutoLayout,而使用CGRectMake的方式将逐渐淘汰掉



界面操作方式:

第三方库Masonry自动布局AutoLayout使用_垂直居中

第三方库Masonry自动布局AutoLayout使用_垂直居中_02

-

第三方库Masonry自动布局AutoLayout使用_边距_03

-

第三方库Masonry自动布局AutoLayout使用_自动布局_04

-----


自动布局第三方库 Masonry(github 一万多个星星 发音:美森瑞)



该库的特点:采用链式语法, 易读


首先了解一下Masonry库的几个常用的类

View+MASAdditions.h

@interface MAS_VIEW (MASAdditions)

@property (nonatomic, strong, readonly) MASViewAttribute *mas_left;    // x坐标
@property (nonatomic, strong, readonly) MASViewAttribute *mas_top;     // y坐标
@property (nonatomic, strong, readonly) MASViewAttribute *mas_right;   // x + width
@property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;  // y + height
@property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;
@property (nonatomic, strong, readonly) MASViewAttribute *mas_width;   // width
@property (nonatomic, strong, readonly) MASViewAttribute *mas_height;  // height
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX; // (x + width)/2
@property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY; // (y + height)/2
@property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;
@property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);

// 生成约束
- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block;
// 更新常量约束
- (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block;
// 重新生成约束(先删除所有约束,再重新生成新的约束)
- (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block;

@end



@interface MASConstraintMaker : NSObject

@property (nonatomic, strong, readonly) MASConstraint *left;
@property (nonatomic, strong, readonly) MASConstraint *top;
@property (nonatomic, strong, readonly) MASConstraint *right;
@property (nonatomic, strong, readonly) MASConstraint *bottom;
@property (nonatomic, strong, readonly) MASConstraint *leading;
@property (nonatomic, strong, readonly) MASConstraint *trailing;
@property (nonatomic, strong, readonly) MASConstraint *width;
@property (nonatomic, strong, readonly) MASConstraint *height;
@property (nonatomic, strong, readonly) MASConstraint *centerX;
@property (nonatomic, strong, readonly) MASConstraint *centerY;
@property (nonatomic, strong, readonly) MASConstraint *baseline;
@property (nonatomic, strong, readonly) MASConstraint *edges;
@property (nonatomic, strong, readonly) MASConstraint *size;
@property (nonatomic, strong, readonly) MASConstraint *center;

@end



@interface MASConstraint : NSObject

- (MASConstraint * (^)(id attr))equalTo;                // equalTo(superView)
- (MASConstraint * (^)(id attr))greaterThanOrEqualTo;
- (MASConstraint * (^)(id attr))lessThanOrEqualTo;

- (MASConstraint * (^)(id attr))mas_equalTo;		//mas_equalTo(NSNumber|CGPoint|CGSize|UIEdgeInsets)
- (MASConstraint * (^)(id attr))mas_greaterThanOrEqualTo;
- (MASConstraint * (^)(id attr))mas_lessThanOrEqualTo;
- (MASConstraint * (^)(id offset))mas_offset;																										             
- (MASConstraint * (^)(CGFloat offset))offset;
- (MASConstraint * (^)(CGSize offset))sizeOffset;
- (MASConstraint * (^)(CGPoint offset))centerOffset;

- (MASConstraint *)with;
- (MASConstraint *)and;	
- (MASConstraint *)left;
- (MASConstraint *)top;
- (MASConstraint *)right;
- (MASConstraint *)bottom;
- (MASConstraint * (^)(MASEdgeInsets insets))insets;

- (MASConstraint *)leading;- (MASConstraint *)trailing;
- (MASConstraint *)width;- (MASConstraint *)height;

- (MASConstraint *)centerX;
- (MASConstraint *)centerY;

- (MASConstraint *)baseline;
@end


对Masonry的理解

使用Masonry时必须先添加子视图

addSubview,然后再创建约束

mas_makeConstraints 



常用函数:

equalTo(superView)


mas_equalTo(NSNumber|CGPoint|CGSize|UIEdgeInsets)


insets(UIEdgeInsets(top, left, bottom, right))


offset(CGFloat)



有意思的地方是and和with 其实这两个函数什么事情都没做,通过这两个函数进行链式语法的链接,更加的符合人们的语言习惯


- (MASConstraint *)with { 

    return self; 

} 

- (MASConstraint *)and { 

    return self; 

}




约束:

    无论约束怎么组合都必须能让系统计算出 坐标 和 尺寸, 约束过多或不足都会影响系统来计算坐标和尺寸的
在使用Masonry来约束时,首先先想一下使用坐标是怎么计算的,让后 让绝对布局方式转为自动布局方式

约束指定一般使用一下方式:
make.约束.equalTo(superView)[.with.offset(CGFloat)]
make.约束.mas_equalTo(NSNumber|CGPoint|CGSize|UIEdgeInsets)

约束组合方式


一组约束必须能计算出坐标值(x, y)和尺寸(width, height)

// 这两个约束是完全一样的,可以带superView.mas_xxx 也可以省略直接父视图 superView

make.left.greaterThanOrEqualTo(label);
make.left.greaterThanOrEqualTo(label.mas_left);

自动布局允许宽度和高度设置为常量值。如果你想设置视图有一个最小和最大宽度也可以通过约束实现:
//width >= 200 && width <= 400
make.width.greaterThanOrEqualTo(@200);
make.width.lessThanOrEqualTo(@400)

指定常量值
make.top.mas_equalTo(42);
make.height.mas_equalTo(20);
make.size.mas_equalTo(CGSizeMake(50, 100));
make.edges.mas_equalTo(UIEdgeInsetsMake(10, 0, 10, 0));
make.left.equalTo(view).mas_offset(UIEdgeInsetsMake(10, 0, 10, 0));

edges
// make top, left, bottom, right equal view2
make.edges.equalTo(view2);

// make top = superview.top + 5, left = superview.left + 10,
//      bottom = superview.bottom - 15, right = superview.right - 20
make.edges.equalTo(superview).insets(UIEdgeInsetsMake(5, 10, 15, 20))

size
// make width and height greater than or equal to titleLabel
make.size.greaterThanOrEqualTo(titleLabel)

// make width = superview.width + 100, height = superview.height - 50
make.size.equalTo(superview).sizeOffset(CGSizeMake(100, -50))

center
// make centerX and centerY = button1
make.center.equalTo(button1)

// make centerX = superview.centerX - 5, centerY = superview.centerY + 10
make.center.equalTo(superview).centerOffset(CGPointMake(-5, 10))


组合1: 直接指明坐标和尺寸

center  (坐标)     equalTo(superView)


size (尺寸)

  mas_equalTo(CGSize)



组合2:通过设定 上下左右边距 四个方向的边距 来计算控件的坐标

(通过相对于父视图的 顶部边距,左边距来计算坐标) 通过(顶部 底部 边距来计算高度,左右边距来计算宽度)


edges              insets(UIEdgeInsets(top, left, bottom, right))



组合3:(left right  top height)

通过左右边距left right确定宽度和x坐标,通过上边距top确定y坐标,通过高度height确定高度

组合4:(left, top, right) 

       对于UILabel 而言 不需要高度,高度是由字体,字号计算出来的


示例程序:

#import "MainViewController.h"
#import "Masonry.h"

#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;

@interface MainViewController ()

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title = @"Masonry";
    self.view.backgroundColor = [UIColor whiteColor];
    
    [self initCenterView];
}


- (void)initCenterView {
    
    // -------------------superView---------------------
    UIView * superView = [[UIView alloc] init];
    superView.backgroundColor = [UIColor blackColor];
    [self.view addSubview:superView];
    
    WS(this);
    [superView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(this.view);
        make.size.mas_equalTo(CGSizeMake(300, 300));
    }];
    
    // 让一个view略小于其superView(边距为10)-------------------centerView---------------------
    UIView * centerView = [UIView new];
    centerView.backgroundColor = [UIColor redColor];
    [superView addSubview:centerView];
    [centerView mas_makeConstraints:^(MASConstraintMaker *make) {
        // 以下三种方式完全一样
//        make.edges.equalTo(superView).insets(UIEdgeInsetsMake(10, 10, 10, 10));   // edges是指的边缘填充,都是正数值
        
//        make.top.equalTo(superView).with.offset(10);                  // y坐标在父视图y坐标的基础上 加 10px
//        make.left.equalTo(superView).with.offset(10);                 // x坐标在父视图x坐标的基础上 加 10px
//        make.bottom.equalTo(superView).with.offset(-10);              // 子视图的高度相对于父视图的高度 减去10px
//        make.right.equalTo(superView).with.offset(-10);               // 子视图的宽度相对于父视图的宽度 减去10px
        
        make.top.left.bottom.and.right.equalTo(superView).insets(UIEdgeInsetsMake(10, 10, 10, 10));
    }];
    
    
    // 让两个高度为150的view垂直居中且等宽且等间隔排列 间隔为10(自动计算其宽度)
    // -------------------orangeView1---------------------
    UIView * orangeView1 = [UIView new];
    orangeView1.backgroundColor = [UIColor orangeColor];
    [centerView addSubview:orangeView1];
    
    UIView * orangeView2 = [UIView new];
    orangeView2.backgroundColor = [UIColor orangeColor];
    [centerView addSubview:orangeView2];
    
    int padding = 10;
    int height = 250;
    [orangeView1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.mas_equalTo(centerView.mas_centerY);               // 纵向垂直居中, 确定y坐标
        make.height.mas_equalTo(height);                                // 确定高度       height
        make.left.equalTo(centerView.mas_left).with.offset(padding);    // 确定 x坐标
        make.right.equalTo(orangeView2.mas_left).with.offset(-padding); // 右边距为 10
        make.width.equalTo(orangeView2);                                // 确定宽度
    }];
    
    
    // -------------------orangeView2---------------------
    [orangeView2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerY.mas_equalTo(centerView.mas_centerY);               // 垂直居中
        make.height.mas_equalTo(height);                                // 确定高度
        make.left.equalTo(orangeView1.mas_right).with.offset(padding);  // 左边距:第一个视图的右边x坐标 +10
        make.right.equalTo(centerView.mas_right).with.offset(-padding); // 又边距:父视图的x坐标 -10
        make.width.equalTo(orangeView1);                                // 确定宽度
    }];                                                                                                                                          
    UILabel * titleLabel = [UILabel new];
    titleLabel.backgroundColor = [UIColor whiteColor];
    titleLabel.numberOfLines = 0;
    titleLabel.text = @"autolayout hello ----------------";
    titleLabel.tintColor = [UIColor blackColor];
    [orangeView1 addSubview:titleLabel];
    [titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {                                                                         
      // 对于UILabel无需设置高度,因为高度是由字体,字号计算出来的
      make.left.equalTo(orangeView1).offset(10);
      make.top.equalTo(orangeView1).offset(10);
      make.right.equalTo(orangeView1).offset(-10);
    }];                                                                                                                                                  
    // 在UIScrollView顺序排列一些view并自动计算contentSize----------------------------------------------------
    UIScrollView * scrollView = [UIScrollView new];
    scrollView.backgroundColor = [UIColor whiteColor];
    [orangeView2 addSubview:scrollView];
    
    [scrollView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(orangeView2).with.insets(UIEdgeInsetsMake(5, 5, 5, 5));
    }];
    
    UIView * containerView = [UIView new];
    containerView.backgroundColor = [UIColor blackColor];
    [scrollView addSubview:containerView];
    [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(scrollView);
        make.width.equalTo(scrollView); // ??????????
    }];
    
    int count = 10;
    UIView * lastView = nil;
    for (int i = 1; i < count; i++) {
        UIView * subView = [UIView new];
        subView.backgroundColor = [UIColor colorWithHue:(arc4random() % 256 / 256.0)
                                             saturation:(arc4random() % 128 / 256.0) + 0.5
                                             brightness:(arc4random() % 128 / 256.0) + 0.5
                                                  alpha:1];
        [containerView addSubview:subView];
        [subView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.and.right.equalTo(containerView);
            make.height.mas_equalTo(@(20 * i));
            if (lastView != nil) {
                make.top.mas_equalTo(lastView.mas_bottom);
            } else {
                make.top.mas_equalTo(containerView.mas_top);
            }
            
        }];
        
        lastView = subView;
    }
    
    [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(lastView.mas_bottom);
    }];
    
}

@end



运行效果如果:

第三方库Masonry自动布局AutoLayout使用_自动布局_05

Interface Builder AutoLayout(以下两篇文章写的很好,应认真看一下)