前言

  在暑假的项目编写过程中,大量使用到了视图布局,笔者用的较多的是Frame Layout(框架布局),该布局方法需要自己计算每个视图的位置,且稍有不注意就会出现视图重叠,导致实际和预期相差较大,使用过程中感觉到了诸多不便,于是有了这篇关于Masonry的基本使用方法的学习。

常用的布局方法

在 Xcode 中,有多种方法可以进行界面布局,每种方法都有其适用的场景。以下是一些常用的布局方法:

  1. Auto Layout(自动布局)
    Auto Layout 是 Xcode 中最强大的布局系统,它使用约束来定义视图的位置和大小。这种方法非常适合创建响应式和灵活的界面。

Interface Builder:在 Xcode 的 Interface Builder 中,你可以通过拖放视图和添加约束来设计界面。这种方式是可视化的,非常适合快速布局。
编程方式:你也可以通过编程的方式来添加和管理约束。使用 NSLayoutConstraint 类来创建和激活约束。

  1. Stack View(堆栈视图)
    UIStackView 是一个容器视图,可以自动管理其子视图的布局。它提供了一个简单的 API 来创建水平或垂直堆栈的布局。

Interface Builder:在 Interface Builder 中,你可以将多个视图拖放到 UIStackView 中,并设置分布和对齐方式。
编程方式:通过创建 UIStackView 实例并添加子视图,然后设置其 axis、distribution、alignment 和 spacing 属性来编程布局。

  1. Size Classes(尺寸类别)
    尺寸类别是一种响应式布局技术,它允许你根据不同的屏幕尺寸和方向提供不同的布局。

Interface Builder:在 Interface Builder 中,你可以为不同的尺寸类别配置不同的约束和视图。
编程方式:通过检查当前的尺寸类别并相应地调整布局。

  1. Frame Layout(框架布局)
    框架布局是一种基于视图的 frame 属性的布局方法。每个视图的位置和大小都是通过代码精确指定的。

编程方式:通过设置视图的 frame 属性来编程布局。这种方法不推荐用于新的项目,因为它不灵活且难以维护。

  1. Flexbox Layout(弹性盒子布局)
    Flexbox 是一种 CSS 布局模型,也被一些第三方库如 Yoga 引入到 iOS 开发中。它提供了一种灵活的方式来布局、对齐和分配容器中的项目空间。

第三方库:使用如 Yoga 这样的第三方库来实现 Flexbox 布局。

  1. Grid Layout(网格布局)
    网格布局是一种将视图组织成网格的方法。在 iOS 中,你可以使用 UICollectionView 来实现复杂的网格布局。

UICollectionView:通过设置 UICollectionView 的布局为 UICollectionViewFlowLayout 或自定义布局来实现网格布局。

  在前期的学习和使用中,笔者使用较多的是Frame Layout(框架布局),这种布局方法较为麻烦,且灵活性较低,需要编程者不断计算视图位置,容易出现视图重叠的情况。后续笔者会再详细介绍 Auto Layout(自动布局)方法。

Masnory

什么是Masnory

Masonry 是一个 Objective-C 的布局框架,用于在 iOS 和 macOS 应用中创建用户界面。它提供了一个链式编程的 API,使得编写自动布局约束变得简单和直观。Masonry 允许开发者以一种更自然和声明式的方式来设置视图的位置和大小,而不是使用传统的 NSLayoutAnchor 或者 NSLayoutConstraint。

Masnory的安装

通常,我们可以通过 CocoaPods 来安装 Masonry。关于CocoaPods的安装和使用,可参考这两篇文章:
最新cocoapods安装流程
【iOS】Cocoapods的安装以及使用

在Podfile文档中添加以下行:

pod 'Masonry'

然后运行 pod install 来安装库。

Masnory常用的方法

Masonry 是一个 Objective-C 的布局框架,它提供了一种链式编程的方式来简化 Auto Layout 约束的创建。以下是 Masonry 的一些常用方法:

基本约束方法

  • makeConstraints:创建并激活一组约束。
  • remakeConstraints:移除视图上的所有旧约束,并应用一组新的约束。
  • updateConstraints:更新视图上的约束。
  • removeConstraints:移除视图上的特定约束。

约束创建方法

  • equalTo:设置视图的某个属性等于另一个视图的相应属性。
  • greaterThanOrEqualTo:设置视图的某个属性大于或等于另一个视图的相应属性。
  • lessThanOrEqualTo:设置视图的某个属性小于或等于另一个视图的相应属性。
  • equalToConstant:设置视图的某个属性等于一个常数。
  • greaterThanOrEqualToConstant:设置视图的某个属性大于或等于一个常数。
  • lessThanOrEqualToConstant:设置视图的某个属性小于或等于一个常数。

尺寸和位置约束

  • widthheight:设置视图的宽度和高度。
  • topleftbottomright:设置视图相对于其父视图的上、左、下、右边距。
  • centerXcenterY:设置视图在其父视图的水平和垂直中心位置。

边距和间距

  • leadingtrailing:设置视图的前导边和尾随边(在支持从右到左布局的语言中使用)。
  • edges:同时设置视图的上、下、左、右边距。
  • size:同时设置视图的宽度和高度。

尺寸和比例

  • aspectRatio:设置视图的宽高比。

约束组合

  • and:用于链式调用中的连接词,表示“和”。
  • with:用于设置约束的附加参数,如间距、偏移量等。

激活和更新约束

  • install:激活一组约束。
  • layoutIfNeeded:立即布局视图,使约束生效。

示例代码

使用 Masonry 设置约束

#import "Masonry.h"

// 假设你有一个视图叫作 view
UIView *view = [[UIView alloc] init];

// 添加视图到父视图(一定要在添加到父视图之后使用)
[self.view addSubview:view];

// 设置约束
[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(self.view.mas_top).offset(20); // 距离父视图顶部20点
    make.left.equalTo(self.view.mas_left).offset(20); // 距离父视图左边20点
    make.width.mas_equalTo(100); // 宽度100点
    make.height.mas_equalTo(50); // 高度50点
}];

链式调用
Masonry 的一个强大特性是它的链式调用,这使得代码更加简洁:

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.left.and.right.equalTo(self.view).with.insets(UIEdgeInsetsMake(20, 20, 20, 20));
    make.height.mas_equalTo(50);
}];

更新和移除约束:

// 创建约束
MASConstraintMaker *constraints = [view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(@100);
    make.height.equalTo(@50);
}];

// 更新约束
[view mas_remakeConstraints:^(MASConstraintMaker *make) {
    make.width.equalTo(@200);
    make.height.equalTo(@100);
}];

// 移除约束
[view mas_removeConstraints:constraints];

使用时出现的问题

在使用 Masonry 进行自动布局时,可能会遇到一些常见的错误。了解这些错误及其原因可以帮助你更有效地解决问题。以下是一些在使用 Masonry 时可能遇到的错误及其原因:

  1. Ambiguous Layout(模糊布局)

    • 原因:当视图的约束不足以确定其在父视图中的确切位置和大小时,就会出现模糊布局。例如,如果只设置了视图的宽度和高度,而没有设置其相对于父视图的位置约束,就会导致模糊布局。
    • 解决方法:确保每个视图都有完整的约束集,包括位置(顶部、底部、左边、右边)和尺寸(宽度、高度)约束。
  2. Missing Constraints(缺少约束)

    • 原因:如果视图没有足够的约束来确定其在父视图中的位置或大小,就会出现此错误。
    • 解决方法:检查并添加缺失的约束,确保视图的每个属性都有明确的约束。
  3. Conflicting Constraints(冲突的约束)

    • 原因:当视图上的约束相互矛盾时,例如,一个约束将视图的宽度设置为100点,而另一个约束将其宽度设置为150点,就会出现冲突的约束。
    • 解决方法:检查并解决约束之间的冲突。可以通过调整约束的优先级或移除多余的约束来解决。
  4. Not calling superview addSubview: before adding constraints(在添加约束之前没有调用 superview addSubview:

    • 原因:在将视图添加到父视图之前添加约束,会导致约束不生效。
    • 解决方法:确保在调用 addSubview: 将视图添加到父视图之后,再添加约束。
  5. Using mas_makeConstraints without returning block(使用 mas_makeConstraints 时没有返回代码块)

    • 原因mas_makeConstraints 需要一个代码块来定义约束,如果没有提供代码块,约束将不会被创建。
    • 解决方法:确保提供了一个代码块,并在其中定义约束。
  6. Setting translatesAutoresizingMaskIntoConstraints to NO(将 translatesAutoresizingMaskIntoConstraints 设置为 NO)

    • 原因:在使用 Auto Layout 时,应该将视图的 translatesAutoresizingMaskIntoConstraints 属性设置为 NO,以启用 Auto Layout。如果忘记设置,Auto Layout 将不会生效。
    • 解决方法:在添加约束之前,确保将视图的 translatesAutoresizingMaskIntoConstraints 属性设置为 NO。
  7. Not updating constraints when view size changes(视图大小变化时没有更新约束)

    • 原因:当视图的大小或布局发生变化时,如果没有更新约束,可能会导致布局不正确。
    • 解决方法:在视图大小变化时,使用 mas_updateConstraintsmas_remakeConstraints 来更新约束。
  8. Using Masonry with manual frame layout(将 Masonry 与手动帧布局混合使用)

    • 原因:将 Masonry 与手动设置视图位置(frame)的方式混合使用,可能会导致不可预测的布局结果。
    • 解决方法:避免混合使用 Masonry 和手动帧布局。如果需要使用 Auto Layout,确保所有布局都通过 Masonry 或其他 Auto Layout API 来管理。

总结

Masonry 是一个非常流行的库,因为它简化了在 iOS 和 macOS 应用中处理自动布局的过程。学习完基本用法后还需多加练习,希望本篇博客对你有所帮助,如有错误,还请斧正!

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部