博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Coding源码学习第四部分(Masonry介绍与使用(一))
阅读量:4582 次
发布时间:2019-06-09

本文共 13940 字,大约阅读时间需要 46 分钟。

Masonry GitHub:

Masonry是一个轻量级的布局框架,拥有自己的描述语法,采用更优雅的链式语法封装自动布局,简洁明了并具有高可读性,而且同时支持 iOS 和 Mac OS X。Masonry是一个用代码写iOS或OS界面的库,可以代替Auto layout。

example :

1 [view1 mas_makeConstraints:^(MASConstraintMaker *make) {    2 3     // 设置和superView 的边缘的缩进量4     make.edges.equalTo(superview).with.insets(padding);5 6 7 }];

Masonry使用讲解

Masonry 支持的属性:

make 的属性:(MASConstraintMaker:)

1 @interface MASConstraintMaker : NSObject 2  3 /** 4  *    The following properties return a new MASViewConstraint 5  *  with the first item set to the makers associated view and the appropriate MASViewAttribute 6  */ 7 @property (nonatomic, strong, readonly) MASConstraint *left; 8 @property (nonatomic, strong, readonly) MASConstraint *top; 9 @property (nonatomic, strong, readonly) MASConstraint *right;10 @property (nonatomic, strong, readonly) MASConstraint *bottom;11 @property (nonatomic, strong, readonly) MASConstraint *leading;12 @property (nonatomic, strong, readonly) MASConstraint *trailing;13 @property (nonatomic, strong, readonly) MASConstraint *width;14 @property (nonatomic, strong, readonly) MASConstraint *height;15 @property (nonatomic, strong, readonly) MASConstraint *centerX;16 @property (nonatomic, strong, readonly) MASConstraint *centerY;17 @property (nonatomic, strong, readonly) MASConstraint *baseline;

其中leading与left trailing与right 在正常情况下是等价的 但是当一些布局是从右至左时, 则会对调 换句话说就是基本可以不理不用 用left和right就好了

需要添约束的View 的约束的属性:

1 @interface MAS_VIEW (MASAdditions) 2  3 /** 4  *    following properties return a new MASViewAttribute with current view and appropriate NSLayoutAttribute 5  */ 6 @property (nonatomic, strong, readonly) MASViewAttribute *mas_left; 7 @property (nonatomic, strong, readonly) MASViewAttribute *mas_top; 8 @property (nonatomic, strong, readonly) MASViewAttribute *mas_right; 9 @property (nonatomic, strong, readonly) MASViewAttribute *mas_bottom;10 @property (nonatomic, strong, readonly) MASViewAttribute *mas_leading;11 @property (nonatomic, strong, readonly) MASViewAttribute *mas_trailing;12 @property (nonatomic, strong, readonly) MASViewAttribute *mas_width;13 @property (nonatomic, strong, readonly) MASViewAttribute *mas_height;14 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerX;15 @property (nonatomic, strong, readonly) MASViewAttribute *mas_centerY;16 @property (nonatomic, strong, readonly) MASViewAttribute *mas_baseline;17 @property (nonatomic, strong, readonly) MASViewAttribute *(^mas_attribute)(NSLayoutAttribute attr);

Masonry 提供了3个关于约束的方法:

1 - (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *make))block; // mas_makeConstraints 只负责新增约束 Autolayout不能同时存在两条针对于同一对象的约束 否则会报错 2 - (NSArray *)mas_updateConstraints:(void(^)(MASConstraintMaker *make))block; // mas_updateConstraints 针对上面的情况 会更新在block中出现的约束 不会导致出现两个相同约束的情况3 - (NSArray *)mas_remakeConstraints:(void(^)(MASConstraintMaker *make))block; // mas_remakeConstraints 则会清除之前的所有约束 仅保留最新的约束4 三种函数善加利用 就可以应对各种情况了

mas_makeConstraints 是给view添加约束,约束有几种,分别是边距,宽,高,左上右下距离,基准线。

添加过约束后可以有修正,修正有offset(位移)修正和multipliedBy(倍率)修正。

语法一般是 make.equalTo or make.greaterThanOrEqualTo or make.lessThanOrEqualTo + 倍数和位移修正。

注意点1:

使用 mas_makeConstraints方法的元素必须事先添加到父元素的中,例如[self.view addSubview:view];

注意点2:

mas_equalTo 和 equalTo 区别:mas_equalTo 比equalTo多了类型转换操作,一般来说,大多数时候两个方法都是 通用的,但是对于数值元素使用mas_equalTo。对于对象或是多个属性的处理,使用equalTo。特别是多个属性时,必须使用equalTo.

举例 make.left.and.right.equalTo(self.view) ,  make.height.mas_equalTo(@20);

1 #define mas_equalTo(...)                 equalTo(MASBoxValue((__VA_ARGS__)))2 #define mas_greaterThanOrEqualTo(...)    greaterThanOrEqualTo(MASBoxValue((__VA_ARGS__)))3 #define mas_lessThanOrEqualTo(...)       lessThanOrEqualTo(MASBoxValue((__VA_ARGS__)))4 5 #define mas_offset(...)                  valueOffset(MASBoxValue((__VA_ARGS__)))

mas_equalTo 是一个宏,可以看到 mas_equalTo只是对其参数进行了一个BOX操作(装箱) MASBoxValue的定义具体可以看看源代码

所支持的类型 除了NSNumber支持的那些数值类型之外,就只支持CGPoint CGSize UIEdgeInsets

mas_greaterThanOrEqualTo 和 mas_lessThanOrEqualTo 这两个宏还有一个小技巧:

1 #ifdef MAS_SHORTHAND_GLOBALS2 3 #define equalTo(...)                     mas_equalTo(__VA_ARGS__)4 #define greaterThanOrEqualTo(...)        mas_greaterThanOrEqualTo(__VA_ARGS__)5 #define lessThanOrEqualTo(...)           mas_lessThanOrEqualTo(__VA_ARGS__)6 7 #define offset(...)                      mas_offset(__VA_ARGS__)8 9 #endif

定义以下两个宏,在使用Masonry框架时就不需要加mas_前缀了

(定义宏一定要在引入Masonry.h文件之前).

1 //define this constant if you want to use Masonry without the 'mas_' prefix 2 #define MAS_SHORTHAND 3 //define this constant if you want to enable auto-boxing for default syntax 4 #define MAS_SHORTHAND_GLOBALS 5  6 // example 7  8  9 #define MAS_SHORTHAND10 #define MAS_SHORTHAND_GLOBALS11 #import "Masonry.h"

注意点3: 注意到方法with和and,这连个方法其实没有做任何操作,方法只是返回对象本身,这这个方法的左右完全是为了方法写的时候的可读性 。

make.left.and.right.equalTo(self.view);和make.left.right.equalTo(self.view);是完全一样的,但是明显的加了and方法的语句可读性 更好点。

1 #pragma mark - Semantic properties2 3 - (MASConstraint *)with {4     return self;5 }6 7 - (MASConstraint *)and {8     return self;9 }

小技巧:#define WS(weakSelf)  __weak __typeof(&*self)weakSelf = self;  快速的定义一个weakSelf ,用于block 里面,防止循环引用。

示例:

(1) 居中显示一个View :

1     WS(weakSelf); // WS 是上面定义的一个宏 2     // 从此基本可以抛弃CGRectMake 了 3     UIView *sv = [UIView new]; 4     sv.backgroundColor = [UIColor blackColor]; 5     // 在做autoLayout 之前,一定要将view 添加到superView 上,否则会报错 6     [self.view addSubview:sv]; 7     // mas_makeConstraints 就是Masonry 的autoLayout 添加函数,将所需的约束添加到block 中就行了 8     [sv mas_makeConstraints:^(MASConstraintMaker *make) { 9         // 将sv 居中(很容易理解)10         make.center.equalTo(weakSelf.view);11         // 将size 设置为(400 ,400)12         make.size.mas_equalTo(CGSizeMake(400, 400));13     }];

(2)让一个View 略小于其superView(边距是10)

1     // 让一个View 略小于其superView(边框为 10) 2     UIView *sv1 = [UIView new]; 3     sv1.backgroundColor = [UIColor redColor]; 4     [sv addSubview:sv1]; 5     [sv1 mas_makeConstraints:^(MASConstraintMaker *make) { 6         make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10)); 7         // 等价于 8 //        make.top.equalTo(sv).with.offset(10); 9 //        make.left.equalTo(sv).with.offset(10);10 //        make.bottom.equalTo(sv).with.offset(-10);11 //        make.right.equalTo(sv).with.offset(-10);12         // 也等价于13 //        make.top.left.bottom.and.right.equalTo(sv).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));14     }];

可以看到 edges 其实就是top,left,bottom,right的一个简化 分开写也可以 一句话更省事

那么为什么bottom和right里的offset是负数呢? 因为这里计算的是绝对的数值 计算的bottom需要小于sv的底部高度 所以要-10 同理用于right

(3)让两个高度为150 的View 垂直居中且等宽且等间隔排列 间隔是10 (自动计算其宽度)

1     // 初级 让两个高度为150 的View 垂直居中且等宽且等间隔排列 间隔为10 (自动计算其宽度) 2     int padding1 = 10; 3     UIView *sv2 = [UIView new]; 4     sv2.backgroundColor = [UIColor yellowColor]; 5     [sv addSubview:sv2]; 6     UIView *sv3 = [UIView new]; 7     sv3.backgroundColor = [UIColor yellowColor]; 8     [sv addSubview:sv3]; 9     10     [sv2 mas_makeConstraints:^(MASConstraintMaker *make) {11         make.centerY.mas_equalTo(sv.mas_centerY);12         make.left.equalTo(sv.mas_left).with.offset(padding1);13         make.right.equalTo(sv3.mas_left).with.offset(-padding1);14         make.height.mas_equalTo(@150);15         make.width.equalTo(sv3);16     }];17 18     [sv3 mas_makeConstraints:^(MASConstraintMaker *make) {19         make.centerY.mas_equalTo(sv.mas_centerY);20         make.left.equalTo(sv2.mas_right).with.offset(padding1);21         make.right.equalTo(sv.mas_right).with.offset(-padding1);22         make.height.mas_equalTo(@150);23         make.width.equalTo(sv2);24     }];

这里我们在两个子view之间互相设置的约束 可以看到他们的宽度在约束下自动的被计算出来了

(4)在UIScrollerView 顺序排列一些View 并自动计算contentSize

1     // 中级 在UIScrollerView 顺序排列一些View 并自动计算contentSize 2     UIScrollView *scrollView = [UIScrollView new]; 3     scrollView.backgroundColor = [UIColor whiteColor]; 4     [sv addSubview:scrollView]; 5     [scrollView mas_makeConstraints:^(MASConstraintMaker *make) { 6         make.edges.equalTo(sv).with.insets(UIEdgeInsetsMake(5, 5, 5, 5)); // 约束UIScrollerView 的窗口视图的大小四边各缩进sv 5 7     }]; 8     UIView *container = [UIView new]; // 起一个中间层的作用,能够自动计算UIScrollerView 的contentSize 9     [scrollView addSubview:container];10     [container mas_makeConstraints:^(MASConstraintMaker *make) {11         make.edges.equalTo(scrollView); // left right top bottom 12         make.width.equalTo(scrollView);13     }];14     15     int count = 10;16     UIView *lastView = nil;17     for (int i = 1; i <= count; i++) {18         UIView *subV = [UIView new];19         [container addSubview:subV];20         subV.backgroundColor = [UIColor colorWithHue:(arc4random() % 256 / 256.0) saturation:(arc4random() % 128 / 256.0) brightness:(arc4random() % 128 / 256.0) alpha:1]; // 设置背景颜色21         [subV mas_makeConstraints:^(MASConstraintMaker *make) {22             make.left.and.right.equalTo(container);23             make.height.mas_equalTo(@(20 * i)); // 每个子View 的高度不断增大一倍24             if (lastView) {25                 make.top.mas_equalTo(lastView.mas_bottom); // lastView 做中间View 的传递,确定每个小View 的top26             } else {27                 make.top.mas_equalTo(container.mas_top); // 第一个小View 的top 和container 相等28             }29         }];30         lastView = subV;31     }32     33     [container mas_makeConstraints:^(MASConstraintMaker *make) {34         make.bottom.equalTo(lastView.mas_bottom); // container 的bottom 和最后一个小View 的bottom 相等35     }];

(5)横向或者纵向等间隙的排列一组View 

autoLayout并没有直接提供等间隙排列的方法(Masonry的官方demo中也没有对应的案例) 但是参考案例3 我们可以通过一个小技巧来实现这个目的 为此写一个Category

1 #import "UIView+Masonry_LJC.h" 2 #import "Masonry.h" 3  4 @implementation UIView (Masonry_LJC) 5  6 - (void)distributeSpacingHorizontallyWith:(NSArray *)views { 7     NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count + 1]; 8      9     for (int i = 0; i < views.count + 1; ++i) {10         UIView *v = [UIView new];11         [spaces addObject:v];12         [self addSubview:v];13         14         [v mas_makeConstraints:^(MASConstraintMaker *make) {15             make.width.equalTo(v.mas_height); // 宽高相等16         }];17     }18     19     UIView *v0 = spaces[0];20     21     __weak __typeof (&*self) ws = self;22     23     [v0 mas_makeConstraints:^(MASConstraintMaker *make) {24         make.left.equalTo(ws.mas_left);25         make.centerY.equalTo(((UIView *)views[0]).mas_centerY);26     }];27     28     UIView *lastSpace = v0;29     for (int i = 0; i < views.count; ++i) {30         UIView *obj = views[i];31         UIView *space = spaces[i + 1];32         33         [obj mas_makeConstraints:^(MASConstraintMaker *make) {34             make.left.equalTo(lastSpace.mas_right);35         }];36         37         [space mas_makeConstraints:^(MASConstraintMaker *make) {38             make.left.equalTo(obj.mas_right);39             make.centerY.equalTo(obj.mas_centerY);40             make.width.equalTo(v0);41         }];42         43         lastSpace = space;44     }45     46     [lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {47         make.right.equalTo(ws.mas_right);48     }];49 }50 51 - (void)distributeSpacingVerticallyWith:(NSArray *)views {52     NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count + 1];53     54     for (int i = 0; i < views.count + 1; ++i) {55         UIView *v = [UIView new];56         [spaces addObject:v];57         [self addSubview:v];58         59         [v mas_makeConstraints:^(MASConstraintMaker *make) {60             make.width.equalTo(v.mas_height);61         }];62     }63     64     UIView *v0 = spaces[0];65     66     __weak __typeof (&*self) ws = self;67     68     [v0 mas_makeConstraints:^(MASConstraintMaker *make) {69         make.top.equalTo(ws.mas_top);70         make.centerX.equalTo(((UIView *)views[0]).mas_centerX);71     }];72     73     UIView *lastSpace = v0;74     for (int i = 0; i < views.count; ++i) {75         UIView *obj = views[i];76         UIView *space = spaces[i + 1];77         78         [obj mas_makeConstraints:^(MASConstraintMaker *make) {79             make.top.equalTo(lastSpace.mas_bottom);80         }];81         82         [space mas_makeConstraints:^(MASConstraintMaker *make) {83             make.top.equalTo(obj.mas_bottom);84             make.centerX.equalTo(obj.mas_centerX);85             make.height.equalTo(v0);86         }];87         88         lastSpace = space;89     }90     91     [lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {92         make.bottom.equalTo(ws.mas_bottom);93     }];94 }95 @end

测试:

1     UIView *sv11 = [UIView new]; 2     UIView *sv12 = [UIView new]; 3     UIView *sv13 = [UIView new]; 4     UIView *sv21 = [UIView new]; 5     UIView *sv31 = [UIView new]; 6     sv11.backgroundColor = [UIColor redColor]; 7     sv12.backgroundColor = [UIColor redColor]; 8     sv13.backgroundColor = [UIColor redColor]; 9     sv21.backgroundColor = [UIColor redColor];10     sv31.backgroundColor = [UIColor redColor];11     [sv addSubview:sv11];12     [sv addSubview:sv12];13     [sv addSubview:sv13];14     [sv addSubview:sv21];15     [sv addSubview:sv31];16     //给予不同的大小 测试效果17     [sv11 mas_makeConstraints:^(MASConstraintMaker *make) {18         make.centerY.equalTo(@[sv12,sv13]);19         make.centerX.equalTo(@[sv21,sv31]);20         make.size.mas_equalTo(CGSizeMake(40, 40));21     }];22     [sv12 mas_makeConstraints:^(MASConstraintMaker *make) {23         make.size.mas_equalTo(CGSizeMake(70, 20));24     }];25     [sv13 mas_makeConstraints:^(MASConstraintMaker *make) {26         make.size.mas_equalTo(CGSizeMake(50, 50));27     }];28     [sv21 mas_makeConstraints:^(MASConstraintMaker *make) {29         make.size.mas_equalTo(CGSizeMake(50, 20));30     }];31     [sv31 mas_makeConstraints:^(MASConstraintMaker *make) {32         make.size.mas_equalTo(CGSizeMake(40, 60));33     }];34     [sv distributeSpacingHorizontallyWith:@[sv11,sv12,sv13]];35     [sv distributeSpacingVerticallyWith:@[sv11,sv21,sv31]];

可以看下这个较复杂页面的约束,其中的桃红色的线条都是约束线: 

本篇先到此,下篇做更深入的学习。

 

转载于:https://www.cnblogs.com/chmhml/p/5735074.html

你可能感兴趣的文章
DVWA-CSRF
查看>>
ubuntu common software introduction
查看>>
资源相互引用时 需添加 PerformSubstitution=True
查看>>
MapRedece(单表关联)
查看>>
蒲公英App开发之检测新版本
查看>>
【安卓基础】倒计时按钮封装(验证码倒计时按钮)
查看>>
configparser模块
查看>>
SelectQueryBuilder的用法
查看>>
android的用户定位(一)
查看>>
creat-react-app搭建的项目中按需引入antd以及配置Less和如何修改antd的主题色
查看>>
IIS安装
查看>>
html块级元素和行级元素的区别和使用
查看>>
for循环嵌套
查看>>
寒冬夜行人
查看>>
poj1151 Atlantis
查看>>
HTML页面之间的参数传递
查看>>
java面试题集锦
查看>>
scikit-learn:4.2.3. Text feature extraction
查看>>
Spring Security构建Rest服务-0800-Spring Security图片验证码
查看>>
AE待整理
查看>>