「OC」自动布局Masonry的运用

「OC」自动布局Masonry的运用

前言

笔者在前面写过关于OC自带的系统自动布局,自动布局的好处就是控件的位置都是相对的,这样即使在不同屏幕尺寸的手机之中的布局都是大致相同的,比frame布局来的更加智能。方便是方便但是我在使用的过程之中发现,使用系统自带的自动布局代码量多且过程繁琐,我们还需要了解在OC之中各个边的名字,这样子好像也不够方便。最近才知道有第三方库Masonry这个工具(难怪当时学习自动布局的时候,网上相关的资料很少)

自动布局

在这里顺带提一嘴frame布局和自动布局的差别

Frame布局方式在简单情况下,较为简单,而且性能极高,但是不利于扩展,当手机的尺寸不同或者横竖屏的时候布局都会有一定的问题,如果想要解决一般来说就是使用几套frame布局。反观自动布局布局,使用起来较为方便,可以轻松应对各种布局方式,但是会消耗一定的性能,使用不当容易造成性能问题。

首先我们来看使用官方自带的自动布局是如何实现的

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor orangeColor];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view];
    
    UILabel *label = [[UILabel alloc] init];
    label.backgroundColor = [UIColor redColor];
    label.text = @"AutoLayout";
    label.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:label];
    
    [NSLayoutConstraint activateConstraints:@[
       [view.topAnchor constraintEqualToAnchor: self.view.safeAreaLayoutGuide.topAnchor constant:200],
       [view.centerYAnchor constraintEqualToAnchor: self.view.centerYAnchor ],
       [view.centerXAnchor constraintEqualToAnchor: self.view.centerXAnchor ],
       [view.heightAnchor constraintEqualToConstant:300],
       [view.widthAnchor constraintEqualToConstant:180],
       
       [label.topAnchor constraintEqualToAnchor:view.topAnchor constant:30],
       [label.centerXAnchor constraintEqualToAnchor: view.centerXAnchor ],
       [label.heightAnchor constraintEqualToConstant:40],
       [label.widthAnchor constraintEqualToConstant:90]
    ]];

}


@end

代码实现的形状如下

image-20240812110732562

NSLayoutConstraint之中就是我们自动布局所需要的代码了,我们还要对控件的translatesAutoresizingMaskIntoConstraints该写为NO,可以看到NSLayoutConstraint之中的代码量还是很多的,所以这也是我们学习Masonry的原因。

Masonry的布局使用

Masonry 是一个流行的 iOS 和 macOS 开发库,用于简化系统自带的 Auto Layout 的使用。它提供了链式语法和便捷的方法,使得创建和管理视图之间的约束变得更加简单和直观。

和系统自带的自动布局比较相似的一个点,那就是Masonry也是通过约束来对控件进行相关的布局,我们使用Masonry进行布局需要以下几个方法

- (NSArray *)mas_makeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;

- (NSArray *)mas_updateConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;

- (NSArray *)mas_remakeConstraints:(void(NS_NOESCAPE ^)(MASConstraintMaker *make))block;

Masonry的使用方式

我们可以将我们前面给出的官方自动布局的代码稍作转化

#import "ViewController.h"
#import "Masonry.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor orangeColor];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:view];
    
    UILabel *label = [[UILabel alloc] init];
    label.backgroundColor = [UIColor redColor];
    label.text = @"AutoLayout";
    label.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:label];
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.view).offset(200);
        make.centerY.equalTo(self.view);
        make.centerX.equalTo(self.view);
        make.height.equalTo(@300);
        make.width.equalTo(@180);
    }];
    
    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view).offset(30);
        make.centerX.equalTo(view);
        make.height.equalTo(@40);
        make.width.equalTo(@90);
    }];
}

@end

注:self.view还可以再被简化,直接用self代替,你就只管偷懒剩下就交给编译器!!!

我们可以看到,我们在创建约束的时候,都没有将对应边写出来,但是系统却帮我们给自动处理了,在这个代码·make.top.equalTo(self.view).offset(200);我们并没有指定这个view去对齐self.view的top,但是系统就进行自动对应了,十分的方便,但如果我们不要进行对应边进行对应,我们也可以使用指定边进行布局操作。

例如:我们将label对top去对应view的bottom,那么我们作出以下修改,可以得到

[label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view.mas_bottom).offset(30);
        make.centerX.equalTo(view);
        make.height.equalTo(@40);
        make.width.equalTo(@90);
    }];

请添加图片描述

另外,我们在使用数字直接限制控件的高度和宽度的时候,一共有两种写法

make.height.mas_equalTo(40); 

make.height.equalTo(@40);

这两种方式似乎都各有繁琐的地方,那我看到网上有一个小技巧,利用宏定义,可以让代码变得更加的简洁

#define MAS_SHORTHAND_GLOBALS

[label mas_makeConstraints:^(MASConstraintMaker *make) {
   make.height.equalTo(40);
}];

说完了关于常数以及边界的内容,如果我们想要改变约束方程之中的系数,就需要用上multipliedBydividedBy这两个方法了,看到方法我们不难知道,一个是乘法一个除法,如果我们想要控件的宽度为控制器宽度的一半的话,可以用以下方法

[label mas_makeConstraints:^(MASConstraintMaker *make) {
   make.width.equalTo(self).multipliedBy(0.5);
}];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
   make.width.equalTo(self).dividedBy(2);
}];

有了系数,有了常数接下来我们就可以使用我们熟悉的约束的写法了

我们设置label的宽度为控制器尺寸的0.5倍在多20个像素点,代码如下

[label mas_makeConstraints:^(MASConstraintMaker *make) {
  make.width.equalTo(self).offset(20).multipliedBy(0.5);
}];

offset和multipliedBy的位置可以互换,不影响实现

一般来说我们的约束都是对控件的四条边进行操作的,那这样就要写四行代码,还是有一点麻烦的,那我们可以使用以下方法,再进行简化

[label mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(self).with.insets(UIEdgeInsetsMake(10, 10, 10, 10));
}];

以上代码我们就是将label限制在了,上左下右边距各为10,我们会发现这个set的设置与之前之前的接触的不太一样,按之前的习惯如果要设置内边距的话,其实应该是设置为(10,10,-10,-10),但是这个编译器帮我们进行了自动处理,所以就变成以上代码的内容,需要注意

Masonry的优先级

Masonry为我们提供了三个优先级的方法,priorityLow()priorityMedium()priorityHigh(),这三个方法内部对应着不同的默认优先级,当然我们也可以使用priority() 括号之中添加数字设置具体的数值。

优先级的方法相等于的数值大小
priorityLow()250
priorityMedium()500
priorityHigh()750
[label mas_makeConstraints:^(MASConstraintMaker *make) {
   make.width.equalTo(view).priorityLow();
   make.width.equalTo(@[view,@100]).priorityHigh();
   make.width.equalTo(@300).priority(888);
}];

优先级的用处是在于,如果我们在约束发生冲突的时候,而且我们也不想将约束删除的话,会优先实现优先级更高的。系统通过比较两个”相互冲突的约束”的优先级,从而忽略低优先级的某个约束,达到正确布局的目的约束优先级默认都是1000。

参考资料

浅谈Masonry的使用技巧

浅谈Constraints,Layout,Display的点点滴滴

  • 19
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值