这篇文章是用UILabel配合模型来实现不同宽度的标签、今后我会出一篇用UICollectionView来实现同样的效果
源码地址:https://github.com/chenfanfang/CollectionsOfExample
附上几张效果图
gif效果图
png效果图
实现思路
1、模型中的主要思路
模型的属性如下:
#import <Foundation/Foundation.h>
/**
* 不同宽度标签的模型
*/
@interface FFDifferentWidthTagModel : NSObject
/** 标签数组 */
@property (nonatomic, strong) NSMutableArray<NSString *> *tagsArrM;
/** 标签数组对应label的frame 数组 */
@property (nonatomic, strong) NSMutableArray<NSValue *> *tagsLabelFramesM;
/** 名字 */
@property (nonatomic, copy) NSString *name;
/** cell的高度 */
@property (nonatomic, assign) CGFloat cellHeight;
@end *tagsArrM;
在给模型标签数组属性tagsArrM赋值的时候,在模型里计算出标签内容对应UILabel的frame,并且将frame保存到模型的tagsLabelFramesM数组中。
并且在模型的.m文件中写cellHeight属性的get方法,这样,控制器就可以获取到对应cell的高度
//cellHeight的get方法
- (CGFloat)cellHeight {
NSValue *frameValue = self.tagsLabelFramesM.lastObject;
CGRect frame = [frameValue CGRectValue];
CGFloat maxY = CGRectGetMaxY(frame);
return maxY + cellMarginY;
}
2、cell中的思路
cell的.h有一个模型属性
/** 不同宽度标签的模型 */
@property (nonatomic, strong)FFDifferentWidthTagModel *tagModel;
在cell.m文件里写tagModel的set方法,根据模型的标签数组中标签的个数产生对应UILabel的个数,并且进行frame、text的赋值。主要代码如下:
- (void)setTagModel:(FFDifferentWidthTagModel *)tagModel {
if (tagModel == _tagModel || tagModel == nil) {
return;
}
_tagModel = tagModel;
//移除所有标签label
for (UILabel *label in self.labelArrM) {
[label removeFromSuperview];
}
self.labelArrM = nil;
//创建label
for (int i = 0; i < tagModel.tagsArrM.count; i++) {
NSValue *frameValue = tagModel.tagsLabelFramesM[i];
CGRect frame = [frameValue CGRectValue];
NSString *title = tagModel.tagsArrM[i];
UILabel *label = [UILabel new];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.font = FFFont(17);
label.frame = frame;
label.layer.cornerRadius = frame.size.height * 0.5;
label.clipsToBounds = YES;
label.text = title;
NSInteger randamNumber = arc4random_uniform((int)self.colorArrM.count);
label.backgroundColor = self.colorArrM[randamNumber];
[self addSubview:label];
[self.labelArrM addObject:label];
}
}
3、控制器的主要思路
控制器没有什么思路,就是产生一些数据源。附上控制器的tableView的数据源方法、代理方法代码
/***********************************UITableViewDataSource***********************************/
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataSourceArr.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FFDifferentWidthTagCell *cell = [tableView dequeueReusableCellWithIdentifier:FFDifferentWidthTagCellID];
cell.tagModel = self.dataSourceArr[indexPath.section];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
/***********************************UITableViewDelegate***********************************/
#pragma mark - UITableViewDelegate
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
FFTableSectionHeaderView *headerView = [FFTableSectionHeaderView new];
[headerView setTitleColor:[UIColor purpleColor]];
FFDifferentWidthTagModel *model = self.dataSourceArr[section];
headerView.title = [NSString stringWithFormat:@"对%@的印象",model.name];
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 36;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
FFDifferentWidthTagModel *model = self.dataSourceArr[indexPath.section];
return model.cellHeight;
}
附上所有代码:
也可以下载源码查看
源码地址:https://github.com/chenfanfang/CollectionsOfExample
//模型.h文件
//
// FFDifferentWidthTagModel.h
// CollectionsOfExample
//
// Created by mac on 16/7/17.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
* 不同宽度标签的模型
*/
@interface FFDifferentWidthTagModel : NSObject
/** 标签数组 */
@property (nonatomic, strong) NSMutableArray<NSString *> *tagsArrM;
/** 标签数组对应label的frame 数组 */
@property (nonatomic, strong) NSMutableArray<NSValue *> *tagsLabelFramesM;
/** 名字 */
@property (nonatomic, copy) NSString *name;
/** cell的高度 */
@property (nonatomic, assign) CGFloat cellHeight;
@end
//模型.m文件
//
// FFDifferentWidthTagModel.m
// CollectionsOfExample
//
// Created by mac on 16/7/17.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import "FFDifferentWidthTagModel.h"
@implementation FFDifferentWidthTagModel
static CGFloat cellMarginY = 16;
/**
* 重写标签数组,根据字符串的内容,计算出字符串的size,再根据size计算出对应UILabel的frame,
* 将计算好的frame存放到数组 tagsLabelFramesM中
*
*/
- (void)setTagsArrM:(NSMutableArray<NSString *> *)tagsArrM {
_tagsArrM = tagsArrM;
CGFloat basedWidth = 37;
CGFloat basedHeight = 30;
//x坐标的边距
CGFloat marginX = 16;
//y坐标的边距
CGFloat marginY = cellMarginY;
CGFloat x = marginX; //x
CGFloat y = marginY; //y
CGFloat w; //宽
CGFloat h = basedHeight; //高
_tagsLabelFramesM = nil; //为了安全起见,将UILabel的frame置空
for (int i = 0; i < tagsArrM.count; i++) {
NSString *str = tagsArrM[i]; //取出标签的内容
//FFFont是字体大小的宏 可以下载源码查看
//FFScreenW是屏幕宽度的宏
//计算标签内容的大小
CGSize size = [str sizeWithFont:FFFont(17) maxSize:CGSizeMake(FFScreenW, 22)];
w = basedWidth + size.width;
CGFloat maxX = x + w;
//maxX 超出这行所允许的范围,另起一行
if (maxX >= (FFScreenW - marginX)) {
x = marginX;
y = y + marginY + basedHeight;
}
CGRect frame = CGRectMake(x, y, w, h);
//CGrect是结构体,不能保存到数组,可以将CGrect转换成NSValue
NSValue *frameValue = [NSValue valueWithCGRect:frame];
//将转换好的frame存到数组中
[self.tagsLabelFramesM addObject:frameValue];
x = x + marginX + w;
}
}
/***********************************懒加载***********************************/
#pragma mark - 懒加载
- (NSMutableArray *)tagsLabelFramesM {
if (_tagsLabelFramesM == nil) {
_tagsLabelFramesM = [NSMutableArray array];
}
return _tagsLabelFramesM;
}
//cellHeight的get方法
- (CGFloat)cellHeight {
NSValue *frameValue = self.tagsLabelFramesM.lastObject;
CGRect frame = [frameValue CGRectValue];
CGFloat maxY = CGRectGetMaxY(frame);
return maxY + cellMarginY;
}
@end
cell.h文件
//
// FFDifferentWidthTagCell.h
// CollectionsOfExample
//
// Created by mac on 16/7/17.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import <UIKit/UIKit.h>
@class FFDifferentWidthTagModel;
@interface FFDifferentWidthTagCell : UITableViewCell
/** 不同宽度标签的模型 */
@property (nonatomic, strong)FFDifferentWidthTagModel *tagModel;
@end
cell.m文件
//
// FFDifferentWidthTagCell.m
// CollectionsOfExample
//
// Created by mac on 16/7/17.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import "FFDifferentWidthTagCell.h"
//model
#import "FFDifferentWidthTagModel.h"
@interface FFDifferentWidthTagCell()
/** label的数组 */
@property (nonatomic, strong) NSMutableArray<UILabel *> *labelArrM;
/** 颜色的数组 */
@property (nonatomic, strong) NSMutableArray<UIColor *> *colorArrM;
@end
@implementation FFDifferentWidthTagCell
/***********************************set方法***********************************/
#pragma mark - set方法
- (void)setTagModel:(FFDifferentWidthTagModel *)tagModel {
if (tagModel == _tagModel || tagModel == nil) {
return;
}
_tagModel = tagModel;
//移除所有标签label
for (UILabel *label in self.labelArrM) {
[label removeFromSuperview];
}
self.labelArrM = nil;
//创建label
for (int i = 0; i < tagModel.tagsArrM.count; i++) {
NSValue *frameValue = tagModel.tagsLabelFramesM[i];
CGRect frame = [frameValue CGRectValue];
NSString *title = tagModel.tagsArrM[i];
UILabel *label = [UILabel new];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.font = FFFont(17);
label.frame = frame;
label.layer.cornerRadius = frame.size.height * 0.5;
label.clipsToBounds = YES;
label.text = title;
NSInteger randamNumber = arc4random_uniform((int)self.colorArrM.count);
label.backgroundColor = self.colorArrM[randamNumber];
[self addSubview:label];
[self.labelArrM addObject:label];
}
}
/***********************************懒加载***********************************/
#pragma mark - 懒加载
- (NSMutableArray<UILabel *> *)labelArrM {
if (_labelArrM == nil) {
_labelArrM = [NSMutableArray array];
}
return _labelArrM;
}
- (NSMutableArray<UIColor *> *)colorArrM {
if (_colorArrM == nil) {
_colorArrM = [NSMutableArray array];
UIColor *redColor = FFColor(214, 67, 67);
UIColor *blueColor = FFColor(74, 144, 226);
UIColor *yellowColor = FFColor(245, 166, 35);
UIColor *greenColor = FFColor(68, 186, 119);
UIColor *purpleColor = [UIColor purpleColor];
[_colorArrM addObject:redColor];
[_colorArrM addObject:blueColor];
[_colorArrM addObject:yellowColor];
[_colorArrM addObject:greenColor];
[_colorArrM addObject:purpleColor];
}
return _colorArrM;
}
@end
控制器.m文件
//
// FFDifferentWidthTagVC.m
// CollectionsOfExample
//
// Created by mac on 16/7/17.
// Copyright © 2016年 chenfanfang. All rights reserved.
//
#import "FFDifferentWidthTagVC.h"
//model
#import "FFDifferentWidthTagModel.h"
//cell
#import "FFDifferentWidthTagCell.h"
@interface FFDifferentWidthTagVC ()<UITableViewDataSource, UITableViewDelegate>
/** 数据源数组 */
@property (nonatomic, strong) NSMutableArray<FFDifferentWidthTagModel *> *dataSourceArr;
/** section头部标题数组 */
@property (nonatomic, strong) NSArray *sectionHeaderTitleArr;
/** 存放标签的数组 */
@property (nonatomic, strong) NSArray *tagArr;
@end
@implementation FFDifferentWidthTagVC
/***********************************生命周期***********************************/
#pragma mark - 生命周期
- (void)viewDidLoad {
[super viewDidLoad];
[self setup];
}
/***********************************初始化***********************************/
#pragma mark - 初始化
static NSString *const FFDifferentWidthTagCellID = @"FFDifferentWidthTagCell";
- (void)setup {
//navTitle
self.navigationItem.title = @"不同宽度的标签";
UITableView *tableView = [[UITableView alloc] init];
tableView.frame = self.view.bounds;
tableView.delegate = self;
tableView.dataSource = self;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
//注册cell FFRegisterCellClass是自定义的宏,具体可以下载源码查看
FFRegisterCellClass(tableView, FFDifferentWidthTagCell, FFDifferentWidthTagCellID);
[self.view addSubview:tableView];
}
/***********************************懒加载***********************************/
#pragma mark - 懒加载
- (NSMutableArray<FFDifferentWidthTagModel *> *)dataSourceArr {
if (_dataSourceArr == nil) {
_dataSourceArr = [NSMutableArray array];
//以下for循环是为了产生随机个数、随机标签的数据源,读者不必研究以下for循环代码
for (int i = 0; i < 4; i++) {
FFDifferentWidthTagModel *model = [FFDifferentWidthTagModel new];
model.name = self.sectionHeaderTitleArr[i];
//产生一个不为0的随机数
int tagNum = 0;
while (tagNum == 0) {
tagNum = arc4random_uniform((int)self.tagArr.count);
}
NSMutableArray *tagsArrM = [NSMutableArray array];
for (int j = 0; j < tagNum; j++) {
int randomTagIndex = arc4random_uniform((int)self.tagArr.count);
[tagsArrM addObject:self.tagArr[randomTagIndex]];
}
model.tagsArrM = tagsArrM;
[_dataSourceArr addObject:model];
}
}
return _dataSourceArr;
}
- (NSArray *)tagArr {
if (_tagArr == nil) {
_tagArr = @[
@"乖巧",
@"喜欢你",
@"纯洁",
@"好漂亮",
@"脱俗、大方、机灵",
@"淑女、秀外慧中、慧指兰心",
@"清水芙蓉、活泼机灵",
@"古怪、可爱",
@"乐观开朗",
@"嫁给我",
@"大义凛然",
@"母仪天下",
@"眉清目秀、可爱",
@"亭亭玉立",
@"闭月羞花",
@"楚楚动人",
@"国色天香",
@"花容月貌",
@"美如冠玉",
@"冰清玉洁",
@"尊重典雅",
@"温柔贤慧",
@"娴淑善良",
@"纤纤有礼",
@"上得厅房 下得厨房",
@"沉鱼落雁 委婉大方"
];
}
return _tagArr;
}
- (NSArray *)sectionHeaderTitleArr {
if (_sectionHeaderTitleArr == nil) {
_sectionHeaderTitleArr = @[
@"Abby",
@"ever",
@"Rose",
@"Alisa",
@"Angelia",
@"Amanda",
@"Anne",
@"Carrie",
@"Cassie"
];
}
return _sectionHeaderTitleArr;
}
/***********************************UITableViewDataSource***********************************/
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataSourceArr.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FFDifferentWidthTagCell *cell = [tableView dequeueReusableCellWithIdentifier:FFDifferentWidthTagCellID];
cell.tagModel = self.dataSourceArr[indexPath.section];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
/***********************************UITableViewDelegate***********************************/
#pragma mark - UITableViewDelegate
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
FFTableSectionHeaderView *headerView = [FFTableSectionHeaderView new];
[headerView setTitleColor:[UIColor purpleColor]];
FFDifferentWidthTagModel *model = self.dataSourceArr[section];
headerView.title = [NSString stringWithFormat:@"对%@的印象",model.name];
return headerView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 36;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
FFDifferentWidthTagModel *model = self.dataSourceArr[indexPath.section];
return model.cellHeight;
}
@end