iOS Masonry实现高度自适应的宫格布局

作者: 邓布利多教授 | 来源:发表于2019-07-23 16:31 被阅读0次

    首先感谢文章作者糖糖本尊的这篇文章,我觉得思路很好,想法奈斯,copy过来,在原文章的基础上增加了一点自己的代码,记录起来,留着用……

    1、跟原文章一样,首先创建一个自定义View,实现宫格的布局,代码如下:

    • .h文件
    #import <UIKit/UIKit.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface LYButttonsView : UIView
    
    ///本次需要添加宫格的个数
    @property (nonatomic, assign) NSInteger buttonCount;
    ///传入宫格最大个数
    -(instancetype)initWithFrame:(CGRect)frame maxButtonsCount:(NSInteger)maxButtonsCount;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    • .m文件
    #import "LYButttonsView.h"
    
    @interface LYButttonsView()
    
    ///装多宫格的数组,复用视图
    @property (nonatomic, strong) NSMutableArray <UIButton*>* buttons;
    ///容器视图 来自适应九宫格高度
    @property (nonatomic, strong) UIView * containerView;
    ///容器视图的底部约束
    @property (nonatomic, weak) MASConstraint * containerViewConstraintbottom;
    
    @end
    
    @implementation LYButttonsView
    
    -(void)setButtonCount:(NSInteger)buttonCount {
        
        _buttonCount = buttonCount;
        if (_buttonCount != 0) {
            
            //每次重新创建宫格的个数 从容器视图中移除
            [self.containerView.subviews enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (!obj.hidden) {
                    [obj removeFromSuperview];
                    obj.hidden = true;
                }
            }];
            
            //循环从初始化list中取出在添加到容器视图当中
            for (int i = 0; i< buttonCount; i++) {
                UIButton *btn = self.buttons[i];
                [self.containerView addSubview:btn];
                btn.hidden = false;
            }
            CGFloat gridWidth = 80;//格子的宽度
            CGFloat gridHeight = 30;//格子的高度
            NSInteger rowNumber = 3;//每行几个
            
            //间距x,y
            CGFloat marginX = ([UIScreen mainScreen].bounds.size.width - gridWidth * rowNumber) / (rowNumber + 1);
            CGFloat marginY = 20;
            
            for ( int  i = 0; i < self.containerView.subviews.count ; i++) {
                
                UIButton *subv = self.containerView.subviews[i];
                subv.backgroundColor = [UIColor colorWithHue:( arc4random() % 256 / 256.0 )
                                                  saturation:( arc4random() % 128 / 256.0 ) + 0.5
                                                  brightness:( arc4random() % 128 / 256.0 ) + 0.5
                                                       alpha:1];
                
                [subv mas_makeConstraints:^(MASConstraintMaker *make){
                    make.left.mas_equalTo(marginX + i % rowNumber * (gridWidth + marginX));
                    make.top.mas_equalTo(marginY + i / rowNumber * (gridHeight + marginY));
                    make.width.mas_equalTo(gridWidth);
                    make.height.mas_equalTo(gridHeight);
                }];
                
            }
            //卸载上一次容器视图的底部约束
            if (self.containerViewConstraintbottom) {
                [self.containerViewConstraintbottom uninstall];
            }
            //重新生成容器视图的底部约束 参考最后一个宫格的底部
            [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
                self.containerViewConstraintbottom = make.bottom.equalTo(self.containerView.subviews.lastObject).offset(marginY);
            }];
            [self mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.equalTo(self.containerView.mas_bottom);
            }];
            
        }else{
            
            //每次重新创建宫格的个数 从容器视图中移除
            [self.containerView.subviews enumerateObjectsUsingBlock:^(UIButton * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                if (!obj.hidden) {
                    [obj removeFromSuperview];
                    obj.hidden = true;
                }
            }];
            //卸载上一次容器视图的底部约束
            if (self.containerViewConstraintbottom) {
                [self.containerViewConstraintbottom uninstall];
            }
            //重新生成容器视图的底部约束 参考最后一个宫格的底部
            [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
                self.containerViewConstraintbottom = make.bottom.equalTo(self.containerView.mas_top).offset(0);
            }];
            [self mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.equalTo(self.containerView.mas_bottom);
            }];
            
        }
        
    }
    
    - (instancetype)initWithFrame:(CGRect)frame maxButtonsCount:(NSInteger)maxButtonsCount{
        
        self = [super initWithFrame:frame];
        if (self) {
            
            self.backgroundColor = [UIColor groupTableViewBackgroundColor];
            for (int i = 0; i < maxButtonsCount; i++) {
                UIButton * button = [UIButton new];
                button.hidden = true;
                [self.buttons addObject:button];
            }
            [self addSubview:self.containerView];
            [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
                make.left.top.right.equalTo(self);
            }];
            
        }
        return self;
        
    }
    
    /// MARK: ---- 懒加载
    -(NSMutableArray *)buttons {
        if (!_buttons) {
            _buttons = [NSMutableArray array];
        }
        return _buttons;
    }
    -(UIView *)containerView {
        if (!_containerView) {
            _containerView = [UIView new];
        }
        return _containerView;
    }
    
    @end
    

    我在.m文件里增加了对buttonCount个数的判断,处理了在原文中当buttonCount为0的时候可能会出现的崩溃现象,不过原文中作者对buttonCount的个数做了限制,原文中作者对buttonCount的个数要求至少为1。

    2、调用和动态改变buttonCount个数

    • 首先引入头文件#import "LYButttonsView.h"
    • 在- (void)viewDidLoad;方法中(也可以放到任何你喜欢的位置,只要不报错就hang)初始化上面说到的那个自定义View:LYButttonsView,并添加一个参照UILabel,这里和原文是一样的,代码如下:
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        self.view.backgroundColor = [UIColor whiteColor];
        
        LYButttonsView * buttonView = [[LYButttonsView alloc] initWithFrame:CGRectZero maxButtonsCount:100];
        _buttonView = buttonView;
        [self.view addSubview:buttonView];
        //此处不用约束高度 ,已经在内部实现.只需要约束上左右即可
        [buttonView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(self.mas_topLayoutGuide);
            make.left.right.equalTo(self.view);
        }];
        buttonView.buttonCount = 9;
        
        UILabel * textLable = [UILabel new];
        textLable.numberOfLines = 0;
        [self.view addSubview:textLable];
        textLable.text = @"阿里大流口水DJAs角落里拿出DJ阿里大垃圾DNC拉上看到家里可擦JDANCSDHWEIRUEWOIRUNCADJK OIWUI是LDJS得了阿拉山口打飞机埃里克森弹尽粮绝是的法律会计师代理费失联的会计法 随地附近 商店里看风景  商店里看风景是多伦多刷卡缴费 了会计师对方 塑料袋看风景我说了;房间里附近商店里看风景嘚瑟你发;了了;会计师对方破了深刻的金凤凰";
        textLable.textColor = [UIColor darkGrayColor];
        [textLable mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.right.equalTo(self.view);
            make.top.equalTo(buttonView.mas_bottom);
        }];
        
    }
    
    • 对了,还要声明一个实例变量,用来动态改变buttonCount,代码如下:
    @interface UIViewController ()
    
    @property (nonatomic, strong) LYButttonsView * buttonView;
    
    @end
    
    • 在-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event;里实现动态赋值操作,代码如下:
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        
        NSInteger count = arc4random() % 10;
        NSLog(@"self.buttonView.buttonCount = %ld",count);
        self.buttonView.buttonCount = count;
        
    }
    

    全部代码,跟原文不同的地方就是,当buttonCount个数为0的时候,不会出现崩溃的现象,在此特别感谢原作者,这里也只是学习记录,所有版权归原作者所有。

    3、全剧终

    相关文章

      网友评论

        本文标题:iOS Masonry实现高度自适应的宫格布局

        本文链接:https://www.haomeiwen.com/subject/uxlalctx.html