目录
前言
在暑假的项目编写过程中,大量使用到了视图布局,笔者用的较多的是Frame Layout(框架布局),该布局方法需要自己计算每个视图的位置,且稍有不注意就会出现视图重叠,导致实际和预期相差较大,使用过程中感觉到了诸多不便,于是有了这篇关于Masonry的基本使用方法的学习。
常用的布局方法
在 Xcode 中,有多种方法可以进行界面布局,每种方法都有其适用的场景。以下是一些常用的布局方法:
- Auto Layout(自动布局)
Auto Layout 是 Xcode 中最强大的布局系统,它使用约束来定义视图的位置和大小。这种方法非常适合创建响应式和灵活的界面。
Interface Builder:在 Xcode 的 Interface Builder 中,你可以通过拖放视图和添加约束来设计界面。这种方式是可视化的,非常适合快速布局。
编程方式:你也可以通过编程的方式来添加和管理约束。使用 NSLayoutConstraint 类来创建和激活约束。
- Stack View(堆栈视图)
UIStackView 是一个容器视图,可以自动管理其子视图的布局。它提供了一个简单的 API 来创建水平或垂直堆栈的布局。
Interface Builder:在 Interface Builder 中,你可以将多个视图拖放到 UIStackView 中,并设置分布和对齐方式。
编程方式:通过创建 UIStackView 实例并添加子视图,然后设置其 axis、distribution、alignment 和 spacing 属性来编程布局。
- Size Classes(尺寸类别)
尺寸类别是一种响应式布局技术,它允许你根据不同的屏幕尺寸和方向提供不同的布局。
Interface Builder:在 Interface Builder 中,你可以为不同的尺寸类别配置不同的约束和视图。
编程方式:通过检查当前的尺寸类别并相应地调整布局。
- Frame Layout(框架布局)
框架布局是一种基于视图的 frame 属性的布局方法。每个视图的位置和大小都是通过代码精确指定的。
编程方式:通过设置视图的 frame 属性来编程布局。这种方法不推荐用于新的项目,因为它不灵活且难以维护。
- Flexbox Layout(弹性盒子布局)
Flexbox 是一种 CSS 布局模型,也被一些第三方库如 Yoga 引入到 iOS 开发中。它提供了一种灵活的方式来布局、对齐和分配容器中的项目空间。
第三方库:使用如 Yoga 这样的第三方库来实现 Flexbox 布局。
- 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文档中添加以下行:
ruby
pod 'Masonry'
然后运行 pod install 来安装库。
Masnory常用的方法
Masonry 是一个 Objective-C 的布局框架,它提供了一种链式编程的方式来简化 Auto Layout 约束的创建。以下是 Masonry 的一些常用方法:
基本约束方法
makeConstraints
:创建并激活一组约束。remakeConstraints
:移除视图上的所有旧约束,并应用一组新的约束。updateConstraints
:更新视图上的约束。removeConstraints
:移除视图上的特定约束。
约束创建方法
equalTo
:设置视图的某个属性等于另一个视图的相应属性。greaterThanOrEqualTo
:设置视图的某个属性大于或等于另一个视图的相应属性。lessThanOrEqualTo
:设置视图的某个属性小于或等于另一个视图的相应属性。equalToConstant
:设置视图的某个属性等于一个常数。greaterThanOrEqualToConstant
:设置视图的某个属性大于或等于一个常数。lessThanOrEqualToConstant
:设置视图的某个属性小于或等于一个常数。
尺寸和位置约束
width
、height
:设置视图的宽度和高度。top
、left
、bottom
、right
:设置视图相对于其父视图的上、左、下、右边距。centerX
、centerY
:设置视图在其父视图的水平和垂直中心位置。
边距和间距
leading
、trailing
:设置视图的前导边和尾随边(在支持从右到左布局的语言中使用)。edges
:同时设置视图的上、下、左、右边距。size
:同时设置视图的宽度和高度。
尺寸和比例
aspectRatio
:设置视图的宽高比。
约束组合
and
:用于链式调用中的连接词,表示"和"。with
:用于设置约束的附加参数,如间距、偏移量等。
激活和更新约束
install
:激活一组约束。layoutIfNeeded
:立即布局视图,使约束生效。
示例代码
使用 Masonry 设置约束
objectivec
#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 的一个强大特性是它的链式调用,这使得代码更加简洁:
objectivec
[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);
}];
更新和移除约束:
objectivec
// 创建约束
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 时可能遇到的错误及其原因:
-
Ambiguous Layout(模糊布局):
- 原因:当视图的约束不足以确定其在父视图中的确切位置和大小时,就会出现模糊布局。例如,如果只设置了视图的宽度和高度,而没有设置其相对于父视图的位置约束,就会导致模糊布局。
- 解决方法:确保每个视图都有完整的约束集,包括位置(顶部、底部、左边、右边)和尺寸(宽度、高度)约束。
-
Missing Constraints(缺少约束):
- 原因:如果视图没有足够的约束来确定其在父视图中的位置或大小,就会出现此错误。
- 解决方法:检查并添加缺失的约束,确保视图的每个属性都有明确的约束。
-
Conflicting Constraints(冲突的约束):
- 原因:当视图上的约束相互矛盾时,例如,一个约束将视图的宽度设置为100点,而另一个约束将其宽度设置为150点,就会出现冲突的约束。
- 解决方法:检查并解决约束之间的冲突。可以通过调整约束的优先级或移除多余的约束来解决。
-
Not calling
superview addSubview:
before adding constraints(在添加约束之前没有调用superview addSubview:
):- 原因:在将视图添加到父视图之前添加约束,会导致约束不生效。
- 解决方法 :确保在调用
addSubview:
将视图添加到父视图之后,再添加约束。
-
Using
mas_makeConstraints
without returning block(使用mas_makeConstraints
时没有返回代码块):- 原因 :
mas_makeConstraints
需要一个代码块来定义约束,如果没有提供代码块,约束将不会被创建。 - 解决方法:确保提供了一个代码块,并在其中定义约束。
- 原因 :
-
Setting translatesAutoresizingMaskIntoConstraints to NO(将
translatesAutoresizingMaskIntoConstraints
设置为 NO):- 原因 :在使用 Auto Layout 时,应该将视图的
translatesAutoresizingMaskIntoConstraints
属性设置为 NO,以启用 Auto Layout。如果忘记设置,Auto Layout 将不会生效。 - 解决方法 :在添加约束之前,确保将视图的
translatesAutoresizingMaskIntoConstraints
属性设置为 NO。
- 原因 :在使用 Auto Layout 时,应该将视图的
-
Not updating constraints when view size changes(视图大小变化时没有更新约束):
- 原因:当视图的大小或布局发生变化时,如果没有更新约束,可能会导致布局不正确。
- 解决方法 :在视图大小变化时,使用
mas_updateConstraints
或mas_remakeConstraints
来更新约束。
-
Using Masonry with manual frame layout(将 Masonry 与手动帧布局混合使用):
- 原因:将 Masonry 与手动设置视图位置(frame)的方式混合使用,可能会导致不可预测的布局结果。
- 解决方法:避免混合使用 Masonry 和手动帧布局。如果需要使用 Auto Layout,确保所有布局都通过 Masonry 或其他 Auto Layout API 来管理。
总结
Masonry 是一个非常流行的库,因为它简化了在 iOS 和 macOS 应用中处理自动布局的过程。学习完基本用法后还需多加练习,希望本篇博客对你有所帮助,如有错误,还请斧正!