这是一个封装好的类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;
// 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