在iOS中使用Masonry进行布局算是日常操作,但是相似于网页的浮动布局的时候,具体示用意如下.
移除其中的某个元素,剩下的元素就会往某个方向进行移动,在Web端,这种布局方式就叫做浮动布局.
另外还有下面的这种情况,尽管也进行浮动但是依然还另外一边保持着束缚关系,这一种在iOS也是比较常见的束缚情况.
在iOS的Masonry使用实现上述过程其实非常麻烦的,假如是我们基于Masonry,基于这种情况,我们一般会有两种写法,一种是状态穷举法,另外一种是临时视图变量记录法.
状态穷举法就是所有的视图组合情况列举出来而后增加对应的束缚布局.具体示例可以看下面代码.
- (void)loseConstraintsAction { if (!_A.hidden && !_B.hidden && !_C.hidden) { [_A mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).offset(20.0f); }]; [_B mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.A.mas_right).offset(8.0f); }]; [_C mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.B.mas_right).offset(8.0f); }]; } if (!_A.hidden && _B.hidden && !_C.hidden) { [_A mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).offset(20.0f); }]; [_C mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.A.mas_right).offset(8.0f); }]; } if (_A.hidden && _B.hidden && !_C.hidden) { [_C mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(self.view).offset(8.0f); }]; }}
状态穷举法算是非常暴力的方案了.状态穷举法的写法形式多种多样,但是整体思想是一致的, 穷举法尽管了解起来简单, 但是弊端也是显而易见的,代码量却是不容小觑,每添加一种组合,我们就需要多一种束缚方案.....
临时变量记录法就是使用一个临时变量记录与哪个视图建立束缚,具体的代码示例如下所示.
- (void)loseConstraintsAction { UIView *lastView = self.view; if (!_A.hidden) { [_A mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo([lastView isEqual:self.view] ? lastView : lastView.mas_right).offset(20.0f); }]; lastView = _A; } if (!_B.hidden) { [_B mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo([lastView isEqual:self.view] ? lastView : lastView.mas_right).offset(8.0f); }]; lastView = _B; } if (!_C.hidden) { [_C mas_remakeConstraints:^(MASConstraintMaker *make) { make.left.equalTo([lastView isEqual:self.view] ? lastView : lastView.mas_right).offset(8.0f); }]; }}
相比于穷举法,在代码结构上已经有很大的改观,但是整体代码依然让人感觉不是那么满意.
由此骚栋就在想能否可以基于Masonry封装一个库,来实现这种浮动效果呢? 所以我就封装了一个基于Masonry的浮动布局 MasonryFloatLayout.
在说实现之前,我们先看一下如何使用封装好的 MasonryFloatLayout.
#ifndef UIViewFloatLayoutHeader_h#define UIViewFloatLayoutHeader_h#import "Masonry/Masonry.h"#endif /* UIViewFloatLayoutHeader_h */
#import "NSArray+FloatLayout.h"
@property (nonatomic, strong) UIView *firstView;@property (nonatomic, strong) UIView *secondView;@property (nonatomic, strong) UILabel *thirdView;
- (UIView *)firstView { if (_firstView == nil) { _firstView = [[UIView alloc] initWithFrame:CGRectZero]; _firstView.backgroundColor = [UIColor redColor]; } return _firstView;}- (UIView *)secondView { if (_secondView == nil) { _secondView = [[UIView alloc] initWithFrame:CGRectZero]; _secondView.backgroundColor = [UIColor orangeColor]; } return _secondView;}- (UILabel *)thirdView { if (_thirdView == nil) { _thirdView = [[UILabel alloc] initWithFrame:CGRectZero]; _thirdView.backgroundColor = [UIColor blueColor]; _thirdView.textColor = [UIColor whiteColor]; _thirdView.text = @"333333333333"; } return _thirdView;}
mas_remakeFloatLayoutConstraints
给每一个View增加具体的布局.最后再用数组增加浮动布局.具体代码如下所示. [self.firstView mas_remakeFloatLayoutConstraints:^(MASConstraintMaker * _Nonnull make, UIView * _Nonnull lastView, UIView * _Nonnull nextView) { make.left.equalTo(@50); make.height.equalTo(@100); make.width.equalTo(@100); make.lastFloatConstraint.offset(10.0f); make.nextFloatConstraint.offset(-10.0f).priorityHigh(); }]; [self.secondView mas_remakeFloatLayoutConstraints:^(MASConstraintMaker * _Nonnull make, UIView * _Nonnull lastView, UIView * _Nonnull nextView) { make.left.equalTo(@50); make.height.equalTo(@100); make.width.equalTo(@100); make.lastFloatConstraint.offset(30.0f).priorityLow(); make.nextFloatConstraint.offset(-10.0f); }]; [self.thirdView mas_remakeFloatLayoutConstraints:^(MASConstraintMaker * _Nonnull make, UIView * _Nonnull lastView, UIView * _Nonnull nextView) { make.left.equalTo(@50); make.height.equalTo(@100); make.lastFloatConstraint.offset(10.0f); make.nextFloatConstraint.offset(-10.0f); }]; [@[self.thirdView, self.firstView, self.secondView] mas_remakeFloatLayoutConstraintsWithOrientation:FloatLayoutOrientationBottomToTop needLastConstraint:need];
lastFloatConstraint
和 nextFloatConstraint
,这两个属性都是来源于 MASConstraintMaker+FloatLayout,我们可以通过这两个属性增加与上一个View和下一个View的间距关系.@property (nonatomic, strong) MASFloatLayoutConstraint *lastFloatConstraint;@property (nonatomic, strong) MASFloatLayoutConstraint *nextFloatConstraint;
- (MASFloatLayoutConstraint * (^)(MASLayoutPriority priority))priority;- (MASFloatLayoutConstraint * (^)(void))priorityLow;- (MASFloatLayoutConstraint * (^)(void))priorityMedium;- (MASFloatLayoutConstraint * (^)(void))priorityHigh;
mas_remakeFloatLayoutConstraints
方法的Block参数除了常见的MASConstraintMaker *make
之外,还会返回上一个视图lastView
和下一个视图nextView
,当然了,这两个参数有可能是nil
.typedef void(^FloatConstraintMaker)(MASConstraintMaker *make, UIView *lastView, UIView *nextView);
NSArray
的分类 NSArray+FloatLayout
, mas_remakeFloatLayoutConstraintsWithOrientation
方法总共有两个参数.一个是用来设定浮动的方向,另外一个是用来设定最后一个视图与父视图的关系,相似于上一个模块说到的第二种情况.typedef enum : NSUInteger { FloatLayoutOrientationUnknow, // 未知或者者根据自己设置的束缚进行束缚布局 FloatLayoutOrientationLeftToRight, // 从左到右进行布局 FloatLayoutOrientationRightToLeft, // 从右到左进行布局 FloatLayoutOrientationTopToBottom, // 从上到下进行布局 FloatLayoutOrientationBottomToTop, // 从下到上进行布局} FloatLayoutOrientation;/// 执行浮动布局/// @param orientation 相对于父视图的浮动方向/// @param needLastConstraint 能否需要增加最后的束缚- (void)mas_remakeFloatLayoutConstraintsWithOrientation:(FloatLayoutOrientation)orientation needLastConstraint:(BOOL)needLastConstraint;
整体的使用流程就是这样的.整体来说和原来的Masonry布局代码方式没有什么太大区别.具体的示例可以看一下我的Demo.
假如在使用过程中遇到任何疑问欢迎随时找我,骚栋在这里谢谢大家了.