iOS 写一个自动布局高度的标签格子视图

前言:

总能碰到这样的东西,如果要使用UICollectionView来做,有种杀鸡焉用牛刀的感觉,而且,还得自己去算宽度,个人感觉不是很好。以前做这个东西,都是使用计算frame的方法,现在项目里都是用Masonry,所以就用这个框架,写了这个控件,这里记录了写这玩意的宽度,高度,位置排放,的代码思路。

效果图:


标签视图.gif

代码地址:https://github.com/gityuency/ObjectiveCTools
示例代码类名 【FloatScrollViewController】

代码如下:

注意:代码中使用到了 Masonry 框架来进行自动布局,请在使用时,添加到项目中。

YXTagsView.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface YXTagsView : UIView

/// 初始化
- (instancetype)init;
/// 行间距
@property (nonatomic) CGFloat spacingRow;
/// 列间距
@property (nonatomic) CGFloat spacingColumn;
/// 内容缩进
@property (nonatomic) UIEdgeInsets contentInset;
/// 加载小格子
@property (nonatomic, strong) NSArray <NSString *> *arrayTags;

@end

NS_ASSUME_NONNULL_END

YXTagsView.m

#import "YXTagsView.h"
#import <Masonry/Masonry.h>

#pragma mark - 小格子
@interface PaddingLabel : UILabel
@property (nonatomic) UIEdgeInsets insets;
@end

@implementation PaddingLabel
- (instancetype)init {
    self = [super init];
    if (self) {
        _insets = UIEdgeInsetsMake(10, 20, 10, 20);
        self.font = [UIFont boldSystemFontOfSize:14];
        self.textColor = [UIColor whiteColor];
        self.backgroundColor = [UIColor redColor];
        self.clipsToBounds = YES;
        self.textAlignment = NSTextAlignmentCenter;
    }
    return self;
}
- (void)drawTextInRect:(CGRect)rect {
    [super drawTextInRect:UIEdgeInsetsInsetRect(rect, _insets)];
}
- (CGSize)intrinsicContentSize {
    CGSize superContentSize = [super intrinsicContentSize];
    CGFloat width = superContentSize.width + _insets.left + _insets.right;
    CGFloat heigth = superContentSize.height + _insets.top + _insets.bottom;
    return CGSizeMake(width, heigth);
}
@end


#pragma mark - 视图
@interface YXTagsView ()

@property (nonatomic, strong) UIView *containerView;

@end

@implementation YXTagsView

- (instancetype)init {
    self = [super init];
    if (self) {
        _spacingRow = 10;
        _spacingColumn = 10;
        _containerView = [[UIView alloc] init];
        [self addSubview:_containerView];
        [_containerView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self);
        }];
    }
    return self;
}

- (void)setArrayTags:(NSArray<NSString *> *)arrayTags {
    _arrayTags = arrayTags;
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (void)setContentInset:(UIEdgeInsets)contentInset {
    _contentInset = contentInset;
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (void)setSpacingRow:(CGFloat)spacingRow {
    _spacingRow = spacingRow;
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

- (void)setSpacingColumn:(CGFloat)spacingColumn {
    _spacingColumn = spacingColumn;
    [self setNeedsLayout];
    [self layoutIfNeeded];
}

///开始布局格子
- (void)layoutChildItems {
    
    //先把原来的数据移除掉
    for (UIView *v in self.containerView.subviews) {
        [v removeFromSuperview];
    }
    
    self.containerView.backgroundColor = [UIColor brownColor];
    [self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(@(_contentInset));
    }];
    
    //宽度
    CGFloat containerWidth = self.containerView.frame.size.width;
    //如果宽度小于等于0,表示这个视图还没有完成约束,拿不到宽度,也就无法继续做下一步的小格子宽度排布计算
    if (containerWidth <= 0) {
        NSLog(@"❗️❗️❗️❗️ YXTagsView 视图没有宽度,暂不能进行排布!");
        return;
    }
    
    //累计宽度
    CGFloat maxX = 0;
    //记录上一个格子
    PaddingLabel *beforeLabel;
    //记录上一个底部约束
    __block MASConstraint *bottomCons = nil;
    
    //添加新的数据
    for (NSInteger i = 0; i < _arrayTags.count; i ++) {
        
        PaddingLabel *label = [[PaddingLabel alloc] init];
        label.text = _arrayTags[i];
        
        [_containerView addSubview:label];
        //先做一下约束,然后拿到宽度
        [label mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.left.equalTo(_containerView);
        }];
        [label setNeedsLayout];
        [label layoutIfNeeded];
        
        CGFloat labelWidth = label.frame.size.width;
        CGFloat labelHeight = label.frame.size.height;
        label.layer.cornerRadius = labelHeight / 2.0;
        
        if ((maxX + labelWidth + _spacingRow) > containerWidth) { //换到下一行的第一个
            [bottomCons deactivate];
            [label mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.left.equalTo(_containerView);
                make.top.equalTo(beforeLabel.mas_bottom).offset(_spacingColumn);
                bottomCons = make.bottom.equalTo(_containerView);
            }];
            maxX = labelWidth;
        } else { //继续在这一行
            if (beforeLabel) { //同一行 第2,3,4...个
                [bottomCons deactivate];
                [label mas_remakeConstraints:^(MASConstraintMaker *make) {
                    make.left.equalTo(beforeLabel.mas_right).offset(_spacingRow);
                    make.top.equalTo(beforeLabel);
                    bottomCons = make.bottom.equalTo(_containerView);
                }];
                maxX += labelWidth + _spacingRow;
            } else { //第一行第一个
                [label mas_remakeConstraints:^(MASConstraintMaker *make) {
                    make.left.equalTo(_containerView);
                    make.top.equalTo(_containerView);
                    bottomCons = make.bottom.equalTo(_containerView);
                }];
                maxX = labelWidth;
            }
        }
        beforeLabel = label;
    }
}

- (void)layoutSubviews {
    [super layoutSubviews];
    [self layoutChildItems];
}

@end

在ViewController里测试:

#import "ViewController.h"
#import <Masonry/Masonry.h>
#import "YXTagsView.h"

@interface ViewController ()

@property (nonatomic, strong) YXTagsView *tagsView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.tagsView = [[YXTagsView alloc] init];
    _tagsView.arrayTags = @[@"可以", @"在", @"添加到", @"父视图之前", @"设置", @"数据"];
    _tagsView.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:_tagsView];
    [_tagsView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view).offset(20);
        make.right.equalTo(self.view).offset(-20);
        make.top.equalTo(self.view).offset(100); 
        //不用给高度,高度由内部的tags个数自动撑开,只需要设置好这个视图的宽度即可。
    }];
    _tagsView.arrayTags = @[@"也可以", @"在", @"添加到", @"父视图", @"之后", @"设置", @"数据"];
}

- (IBAction)action1:(id)sender {
    NSInteger a = arc4random_uniform(30);
    NSInteger b = arc4random_uniform(30);
    NSInteger c = arc4random_uniform(30);
    NSInteger d = arc4random_uniform(30);
    self.tagsView.contentInset = UIEdgeInsetsMake(a, b, c, d);
}

- (IBAction)action2:(id)sender {
    NSArray *aaaaaa = @[@"愿", @"天", @"堂", @"没", @"有", @"bug", @"从", @"此", @"不", @"写", @"代", @"码"];
    NSMutableArray *tagArray = [NSMutableArray array];
    NSInteger ttttttt = arc4random_uniform(20);
    for (NSInteger j = 0; j < ttttttt; j ++) {
        NSMutableString *s = [[NSMutableString alloc] init];
        NSInteger suijishu = arc4random_uniform(5) + 1; //文字长度随机数
        NSMutableArray *mmmmm = [NSMutableArray arrayWithArray:aaaaaa];
        for (NSInteger i = 0; i < suijishu; i ++) {
            int shuzuchuangdu = (int)mmmmm.count;
            NSInteger k = arc4random_uniform(shuzuchuangdu);
            [s appendFormat:@"%@", mmmmm[k]];
            [mmmmm removeObjectAtIndex:k];
        }
        [tagArray addObject:s];
    }
    NSLog(@"%@", tagArray);
    self.tagsView.arrayTags = tagArray;
}

- (IBAction)action3:(id)sender {
    self.tagsView.spacingRow = arc4random_uniform(30);
    self.tagsView.spacingColumn = arc4random_uniform(30);
}

@end

结语

写几个破代码真的烦死了。

推荐阅读更多精彩内容