天天看点

iOS自定义控件-动态标签展示

最近项目有个需求,能够动态的展示一组数据标签,于是自己动手做了一个自定义的view,此自定义View暂时只是为了实现功能,其他的扩展功能以后有需要再添加。

首先是MViewTextList.h文件

//
//  MViewTagList.h
//  mall
//
//  Created by zyz on 16/3/21.
//  Copyright © 2016年 codeagod. All rights reserved.
//  文字tag展示,支持多选,支持单选

#import <UIKit/UIKit.h>

@class MViewTextList;

@protocol MViewTextListDelegate <NSObject>
/**
 *  代理方法,用户选择某个tag按钮
 */
- (void)viewTextListDidSelectTagViewTextList:(MViewTextList *)viewTextList selectBtn:(UIButton *)selectBtn selectDatas:(NSArray *)selectDatas;
/**
 *  代理方法,用户取消某个tag按钮
 */
- (void)viewTextListDidCancelTagViewTextList:(MViewTextList *)viewTextList cancelBtn:(UIButton *)cancelBtn selectDatas:(NSArray *)selectDatas;

@end

@interface MViewTextList : UIView

#pragma :标签的数据集合
@property (nonatomic,strong) NSArray *datas;
#pragma :选中的数据集合
@property (nonatomic,strong) NSMutableArray *datasSelect;

#pragma :是否单选
@property (nonatomic,assign) BOOL singleSelect;
#pragma :代理
@property (nonatomic,weak) id<MViewTextListDelegate> delegate;

#pragma :字体的大小,如果没有设置会有一个默认的数值
@property (nonatomic,assign) CGFloat textSize;
#pragma :内边距,如果没有设置会有一个默认的数值
@property (nonatomic,assign) CGFloat spaceIn;
#pragma :外边距,如果没有设置会有一个默认的数值
@property (nonatomic,assign) CGFloat spaceOut;
#pragma :普通的背景颜色,如果没有设置,会有一个默认的圆角背景
@property (nonatomic,strong) UIColor *colorNormalBackground;
#pragma :选中的背景颜色,如果没有设置,会有一个默认的圆角背景
@property (nonatomic,strong) UIColor *colorSelectedBackground;
#pragma :普通的字体颜色,如果没有设置,会有一个默认的字体颜色
@property (nonatomic,strong) UIColor *colorNormalText;
#pragma :选中的字体颜色,如果没有设置,会有一个默认的字体颜色
@property (nonatomic,strong) UIColor *colorSelectedText;

@end
           

其次,是MViewTextList.m文件内容

//
//  MViewTagList.m
//  mall
//
//  Created by zyz on 16/3/21.
//  Copyright © 2016年 codeagod. All rights reserved.
//

#import "MViewTextList.h"

#define kDefaultInSpace 10
#define kDefaultOutSpace 10

#define kDefaultTextSize 15

#define kDefaultImageNormalColor ([UIColor grayColor])
#define kDefaultImageSelectedColor ([UIColor whiteColor])

#define kDefaultTextNormalColor ([UIColor whiteColor])
#define kDefaultTextSelectedColor ([UIColor grayColor])

@interface MViewTextList ()

#pragma :选中的标签按钮,单选模式下有效
@property (nonatomic,weak) UIButton *btnSelect;

@end

@implementation MViewTextList

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

- (NSMutableArray *)datasSelect
{
    if (_datasSelect == nil) {
        _datasSelect = [[NSMutableArray alloc] init];
    }
    return _datasSelect;
}

- (void)setDatas:(NSArray *)datas
{
    CGFloat width = self.width;
    
    for (int i = 0;i< datas.count ;i++)
    {
        NSString *strTag = datas[i];
        CGSize realSize = [strTag sizeWithFont:[UIFont systemFontOfSize:self.textSize] maxSize:CGSizeMake(kScreenWidth - 2 * self.spaceOut, CGFLOAT_MAX)];
        if (self.width > 0) {
            if (i == 0) {
                
                UIButton *btn = [self createButtonWithTitle:strTag];
                //设置布局
                btn.frame = CGRectMake(self.spaceOut, self.spaceOut, realSize.width + 2 * self.spaceIn, realSize.height + 2 * self.spaceIn);
                //设置背景
                [self setBtnBackGroundWithBtn:btn];
                
                [self addSubview:btn];
                //重新计算高度
                self.height = btn.height + 2 * self.spaceOut;
            }else{
                
                CGFloat leaveWidth = width -  CGRectGetMaxX([self.subviews lastObject].frame);
                if ((realSize.width + self.spaceOut + 2 * self.spaceIn) > leaveWidth) {
                    /**
                     *  下一行显示
                     */
                    UIButton *btn = [self createButtonWithTitle:strTag];
                    btn.frame = CGRectMake(self.spaceOut, CGRectGetMaxY([self.subviews lastObject].frame) + self.spaceOut, realSize.width + 2 * self.spaceIn, realSize.height + 2 * self.spaceIn);
                    //设置背景
                    [self setBtnBackGroundWithBtn:btn];
                    
                    [self addSubview:btn];
                    
                    //重新计算高度
                    self.height = CGRectGetMaxY([self.subviews lastObject].frame) + self.spaceOut;
                }else{
                    /**
                     *  同一行显示
                     */
                    UIButton *btn = [self createButtonWithTitle:strTag];
                    btn.frame = CGRectMake(CGRectGetMaxX([self.subviews lastObject].frame) + self.spaceOut, [self.subviews lastObject].y, realSize.width + 2 * self.spaceIn, realSize.height + 2 * self.spaceIn);
                    //设置背景
                    [self setBtnBackGroundWithBtn:btn];
                    
                    [self addSubview:btn];
                }
                
            }
            
        }
    }
    
}

/**
 *  设置按钮的背景颜色
 */
- (void)setBtnBackGroundWithBtn:(UIButton *)btn
{
    //设置默认状态背景
    if (self.colorNormalBackground == nil) {
        [btn setBackgroundImage:[UIImage imageFromColor:kDefaultImageNormalColor frame:btn.frame] forState:UIControlStateNormal];
    }else{
        [btn setBackgroundImage:[UIImage imageFromColor:self.colorNormalBackground frame:btn.frame] forState:UIControlStateNormal];
    }
    //设置选中状态背景
    if (self.colorSelectedBackground == nil) {
        [btn setBackgroundImage:[UIImage imageFromColor:kDefaultImageSelectedColor frame:btn.frame] forState:UIControlStateSelected];
    }else{
        [btn setBackgroundImage:[UIImage imageFromColor:self.colorSelectedBackground frame:btn.frame] forState:UIControlStateSelected];
    }
    
}

- (void) setBtnTextColorWithBtn:(UIButton *)btn
{
    //设置普通模式下的字体颜色
    if (self.colorNormalText == nil) {
        [btn setTitleColor:kDefaultTextNormalColor forState:UIControlStateNormal];
    }else{
        [btn setTitleColor:self.colorNormalText forState:UIControlStateNormal];
    }
    //设置选中模式下的字体颜色
    if (self.colorSelectedText == nil) {
        [btn setTitleColor:kDefaultTextSelectedColor forState:UIControlStateSelected];
    }else{
        [btn setTitleColor:self.colorSelectedText forState:UIControlStateSelected];
    }
    
}

/**
 *  创建一个UIButton
 */
- (UIButton *)createButtonWithTitle:(NSString *)title
{
    UIButton *btn = [[UIButton alloc] init];
    //
    btn.layer.masksToBounds = YES;
    //设置圆角
    btn.layer.cornerRadius = 4;
    //设置字体
    btn.titleLabel.font = [UIFont systemFontOfSize:self.textSize];
    //设置字体颜色
    [self setBtnTextColorWithBtn:btn];
    //设置普通模式下的标题
    [btn setTitle:title forState:UIControlStateNormal];
    //设置按钮的点击响应对象的方法
    [btn addTarget:self action:@selector(didTagBtn:) forControlEvents:UIControlEventTouchUpInside];
    
    return btn;
}

- (void)didTagBtn:(UIButton *)btn
{
    if (self.singleSelect) {
        if (!btn.selected) {
            //取消之前的选中选项
            if (self.btnSelect != nil) {
                self.btnSelect.selected = NO;
            }
            //将当前点击的按钮赋给选中按钮
            self.btnSelect = btn;
            //设置选中的按钮为选中状态
            self.btnSelect.selected = YES;
            //移除数据集合里面旧数据
            [self.datasSelect removeAllObjects];
            //增加新数据
            [self.datasSelect addObject:self.btnSelect.currentTitle];
            //响应代理
            if ([self.delegate respondsToSelector:@selector(viewTextListDidSelectTagViewTextList:selectBtn:selectDatas:)]) {
                [self.delegate viewTextListDidSelectTagViewTextList:self selectBtn:btn selectDatas:self.datasSelect];
            }
            
        }
    }else{
        
        if (btn.selected) {
            /**
             *  取消选中效果
             */
            //获取点击的按钮的标题
            NSString *curTitle = btn.currentTitle;
            //如果该标题包含在选中数据集合中,则移除
            if ([self.datasSelect containsObject:curTitle]) {
                [self.datasSelect removeObject:curTitle];
            }
            //响应代理
            btn.selected = NO;
            if ([self.delegate respondsToSelector:@selector(viewTextListDidCancelTagViewTextList:cancelBtn:selectDatas:)]) {
                [self.delegate viewTextListDidCancelTagViewTextList:self cancelBtn:btn selectDatas:self.datasSelect];
            }
        }else{
            
            /**
             *  选中效果
             */
            btn.selected = YES;
            //获取点击的按钮的标题
            NSString *curTitle = btn.currentTitle;
            //如果该标题不包含在选中数据集合中,则添加进去
            if (![self.datasSelect containsObject:curTitle]) {
                [self.datasSelect addObject:curTitle];
            }
            //响应代理
            if ([self.delegate respondsToSelector:@selector(viewTextListDidSelectTagViewTextList:selectBtn:selectDatas:)]) {
                [self.delegate viewTextListDidSelectTagViewTextList:self selectBtn:btn selectDatas:self.datasSelect];
            }
        }
        
    }
    
}




- (CGFloat)spaceIn
{
    
    if (_spaceIn == 0 || _spaceIn < 0) {
        _spaceIn = kDefaultInSpace;
    }
    return _spaceIn;
}

- (CGFloat)spaceOut
{
    if (_spaceOut == 0 || _spaceOut < 0) {
        _spaceOut = kDefaultOutSpace;
    }
    return _spaceOut;
}

- (CGFloat)textSize
{
    if (_textSize == 0 || _textSize < 0) {
        _textSize = kDefaultTextSize;
    }
    return _textSize;
}


@end
           

其次,是调用代码

MViewTextList *viewTextListTag = [[MViewTextList alloc] init];
viewTextListTag.delegate = self;
viewTextListTag.frame = CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 100);
viewTextListTag.spaceIn = 10;//设置内边距,注意此步骤必须在setDatas之前
viewTextListTag.spaceOut = 10;//设置外边距,注意此步骤必须在setDatas之前
//    viewTextListTag.singleSelect = YES;//设置是否单选
viewTextListTag.colorNormalBackground = [UIColor whiteColor];
viewTextListTag.colorSelectedBackground = [UIColor purpleColor];
viewTextListTag.colorNormalText = [UIColor purpleColor];
viewTextListTag.colorSelectedText = [UIColor whiteColor];
    
//设置数据集合,最好在最后进行设置
viewTextListTag.datas =@[@"红",@"橙",@"紫",@"青",@"靛",@"蓝",@"白",@"黑",@"肤色",@"阳光少女",@"魅惑经典",@"都市时尚"];
[self.view addSubview:viewTextListTag];
           

另外,还涉及到一个计算字符串实际大小的方法

创建字符串的扩展类NSString(Extension),之后添加方法

/**
 *  计算文本占用的宽高
 *
 *  @param font    显示的字体
 *  @param maxSize 最大的显示范围
 *
 *  @return 占用的宽高
 */
- (CGSize)sizeWithFont:(UIFont *)font maxSize:(CGSize)maxSize
{
    NSDictionary *dict = @{NSFontAttributeName: font};
    CGSize textSize = [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size;
    return textSize;
}
           

下面是效果图

iOS自定义控件-动态标签展示