这是一个封装好的类TagListView,
1. 只需要调用两个方法 设置宽度,间距,边距 并赋给它需要显示的字符串数组;
2. 遵循tagListView的协议, 并实现返回buttonView的方法.
即可展现.
这里我用了SDAutoLayout, 一个三方布局, 用cocopod安装一下就好;
一下是具体的实现代码 带 注释解释
// TagListView.h 该类的.h文件 #import <UIKit/UIKit.h> @protocol TagListViewDelegate<NSObject> @required - (UIButton *)setItemBtnView; //必须实现方法:返回buttonView @optional - (void)clickWithBtn:(UIButton *)btn idx:(NSInteger)idx; //点击button触发方法 @end typedef void(^ReturnClickBtnArr)(NSArray *btnArr); // 返回已选中的按钮数组 @interface TagListView : UIView @property(nonatomic, strong) UIButton *itemBtn; @property(nonatomic, assign) NSUInteger maxSelectedTags; // 多选值 @property(nonatomic, strong) NSMutableArray *selectedTitles; //已选中的按钮标题数组 @property(nonatomic, weak) id <TagListViewDelegate> delegate; #pragma mark - 设置宽度 间距 边距 - (void)setWid:(CGFloat)wid btnTitlePadding_X:(CGFloat)horizontailX btnTitlePadding_Y:(CGFloat)vertailY marginX:(CGFloat)marginX marginY:(CGFloat)marginY itemHeight:(CGFloat)height; #pragma mark - 设置字符串数组 (该方法必须在setWid...方法后执行) - (void)setTagViewWithTitles:(NSArray *)titleArr; - (NSArray *)getAllSubBtns; @end
// TagListView.m 该类的.m文件 #import "TagListView.h" #import "UIView+SDAutoLayout.h" #define kHorizontalX 7 #define kVerticalY 3 #define kMarginY 10 #define kMarginX 10 @implementation TagListView { CGFloat _horizontailX; // btn的左右间距 CGFloat _vertailY; // btn的上下间距 CGFloat _marginX; // tagView的左右边距 CGFloat _marginY; // tagVIew的上下边距 CGFloat _wid; // tagView的宽度 CGFloat _itemHeight; // btn的高度 NSArray *_titleArray; // 需要展示的字符串数组 } - (instancetype)init { if (self = [super init]) { _horizontailX = kHorizontalX; _vertailY = kVerticalY; _marginX = kMarginY; _marginY = kMarginX; _wid = 0; _maxSelectedTags = 3; //default _selectedTitles = [NSMutableArray array]; } return self; } #pragma mark - 设置宽度 间距 边距 - (void)setWid:(CGFloat)wid btnTitlePadding_X:(CGFloat)horizontailX btnTitlePadding_Y:(CGFloat)vertailY marginX:(CGFloat)marginX marginY:(CGFloat)marginY itemHeight:(CGFloat)height { if (wid) { _wid = wid; } if (horizontailX) { _horizontailX = horizontailX; } if (vertailY) { _vertailY = vertailY; } if (marginX) { _marginX = marginX; } if (marginY) { _marginY = marginY; } if (height) { _itemHeight = height; } } #pragma mark - 设置字符串数组 (该方法必须在setWid...方法后执行) - (void)setTagViewWithTitles:(NSArray *)titleArr { _titleArray = [titleArr copy]; // 清除所有子视图 while (self.subviews.count) { UIView *child = self.subviews.lastObject; [child removeFromSuperview]; } // 若未指定宽度 就 获得当前视图宽度 if (_wid == 0) { [self updateLayout]; _wid = self.width; } __block int totalHeight = 0; __block CGRect previousFrame = CGRectMake(0, 0, 0, 0); __block CGFloat height = 0; // 循环title数组 [titleArr enumerateObjectsUsingBlock:^(NSString *title, NSUInteger idx, BOOL * _Nonnull stop) { UIButton *tag = [self.delegate setItemBtnView]; [tag setTitle:title forState:UIControlStateNormal]; [tag addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside]; tag.tag = idx; // 设置已选中title的选中状态 if ([self.selectedTitles containsObject:title]) { tag.selected = YES; } else { tag.selected = NO; } // 1. 计算size // 获得title字体对应的size NSDictionary *attrs = @{NSFontAttributeName : tag.titleLabel.font}; CGSize Size_str = [title sizeWithAttributes:attrs]; // 给size加上 上下边距 Size_str.width += _horizontailX * 2; if (_itemHeight) { Size_str.height = _itemHeight; } else { Size_str.height += _vertailY * 2; } CGRect newRect = CGRectZero; newRect.size = Size_str; // 2. 计算origin if (CGRectGetMaxX(previousFrame) + Size_str.width + _marginX > _wid) { //换行 newRect.origin = CGPointMake(0, CGRectGetMaxY(previousFrame) + _marginY); totalHeight += Size_str.height + _marginY; } else { //未换行 newRect.origin = CGPointMake((CGRectGetMaxX(previousFrame) == 0 ? 0 : CGRectGetMaxX(previousFrame) + _marginX), previousFrame.origin.y); } [tag setFrame:newRect]; previousFrame = tag.frame; height = totalHeight + Size_str.height; [self addSubview:tag]; }]; self.sd_layout.heightIs(height); } - (NSArray *)getAllSubBtns { return self.subviews; } #pragma mark - btn的点击方法 - (void)onClick:(UIButton *)btn { // 1.如果超出最多选中数 则需把最先选中的删除 if (!btn.selected && self.selectedTitles.count >= _maxSelectedTags){ NSString *title = [self.selectedTitles objectAtIndex:0]; NSUInteger firstSelectedIndex = [_titleArray indexOfObject:title]; if (firstSelectedIndex != NSNotFound) { UIButton *selectedButton = [self.subviews objectAtIndex:firstSelectedIndex]; selectedButton.selected = NO; [self.selectedTitles removeObjectAtIndex:0]; } } long index = btn.tag; NSString *title = [_titleArray objectAtIndex:index]; if (btn.selected) { // 设置为未选中状态 btn.selected = NO; [self.selectedTitles removeObject:title]; } else { // 设置为选中状态 btn.selected = YES; [self.selectedTitles addObject:title]; } // 若delegate包含该方法 则让其执行 if ([self.delegate respondsToSelector:@selector(clickWithBtn:idx:)]) { [self.delegate clickWithBtn:btn idx:index]; } } @end
具体使用如下:
// ViewController.m #import "ViewController.h" #import "UIView+SDAutoLayout.h" #import "TagListView.h" #define kScreenWidth self.view.frame.size.width @interface ViewController ()<TagListViewDelegate> @property (nonatomic, strong)TagListView *tagListView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.tagListView = [[TagListView alloc] init]; self.tagListView.delegate = self; self.tagListView.backgroundColor = [UIColor cyanColor]; self.tagListView.maxSelectedTags = 3; [self.view addSubview:self.tagListView]; self.tagListView.sd_layout.topSpaceToView(self.view, 50).leftSpaceToView(self.view, 16).rightSpaceToView(self.view, 16); // 设置宽度 间距 边距 [self.tagListView setWid:(kScreenWidth - 20) btnTitlePadding_X:20 btnTitlePadding_Y:20 marginX:20 marginY:20 itemHeight:20]; // 设置需要显示的字符串数组 [self.tagListView setTagViewWithTitles:@[@"周一", @"周二", @"周三", @"周四", @"周五", @"礼拜六", @"礼拜天", @"一月", @"二月", @"三月", @"四月", @"五月", @"六月", @"七月", @"八月", @"九月", @"十月", @"十一月", @"十二月", @"春天", @"夏天", @"秋天", @"冬天", @"张三", @"李四", @"王五"]]; } #pragma mark - TagListViewDelegate // 必须实现的协议方法 返回buttonView - (UIButton *)setItemBtnView { UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected]; btn.layer.borderWidth = 0.4; btn.layer.cornerRadius = 2; btn.layer.borderColor = [UIColor grayColor].CGColor; return btn; } @end