IOS动态自适应标签实现
先上效果图

设计要求
1、标签的宽度是按内容自适应的
2、一行显示的标签个数是动态的,放得下就放,放不下就换行
3、默认选中第一个
4、至少选中一个标签
实现思路
首先我们从这个效果上来看,这个标签是有选中和不选中状态,那我们首选的控件肯定就是用 UIButton来实现了。
这个小程度的重点就在于标签能自动换行,还是智能的,不是固定一行多少个那种,这个我们通过计算每个按钮实际宽度与屏幕的宽度进行比较就能判断是否需要换行了。
还有一点就是处理 至少选中一个标签的功能,我这里有一种方式,就是控制按钮的 userInteractionEnabled 属性来实现,如果只有一个按钮的时候就把那一个按钮的这个属性给设置成 NO,这样就禁止用户对它进行点击事件了,这个时候其它按钮是可以正常选中的,只要选中的按钮大于1个,那就把刚才那个按钮属性再改成YES,这样那个按钮就又能点了。
具体看代码
创建一个继承于UIView的 XGTagView 类
//
// XGTagView.h
// 动态标签
//
// Created by xgao on 17/3/22.
// Copyright © 2017年 xgao. All rights reserved.
// #import <UIKit/UIKit.h> @interface XGTagView : UIView /**
* 初始化
*
* @param frame frame
* @param tagArray 标签数组
*
* @return
*/
- (instancetype)initWithFrame:(CGRect)frame tagArray:(NSMutableArray*)tagArray; // 标签数组
@property (nonatomic,retain) NSArray* tagArray; // 选中标签文字颜色
@property (nonatomic,retain) UIColor* textColorSelected;
// 默认标签文字颜色
@property (nonatomic,retain) UIColor* textColorNormal; // 选中标签背景颜色
@property (nonatomic,retain) UIColor* backgroundColorSelected;
// 默认标签背景颜色
@property (nonatomic,retain) UIColor* backgroundColorNormal; @end
//
// XGTagView.m
// 动态标签
//
// Created by xgao on 17/3/22.
// Copyright © 2017年 xgao. All rights reserved.
// #import "XGTagView.h" @interface XGTagView() @end @implementation XGTagView /**
* 初始化
*
* @param frame frame
* @param tagArray 标签数组
*
* @return
*/
- (instancetype)initWithFrame:(CGRect)frame tagArray:(NSArray*)tagArray{ self = [super initWithFrame:frame];
if (self) {
_tagArray = tagArray;
[self setUp];
}
return self;
} // 初始化
- (void)setUp{ // 默认颜色
_textColorNormal = [UIColor darkGrayColor];
_textColorSelected = [UIColor whiteColor];
_backgroundColorSelected = [UIColor redColor];
_backgroundColorNormal = [UIColor whiteColor]; // 创建标签按钮
[self createTagButton];
} // 重写set属性
- (void)setTagArray:(NSMutableArray *)tagArray{ _tagArray = tagArray; // 重新创建标签
[self resetTagButton];
} - (void)setTextColorSelected:(UIColor *)textColorSelected{ _textColorSelected = textColorSelected;
// 重新创建标签
[self resetTagButton];
} - (void)setTextColorNormal:(UIColor *)textColorNormal{ _textColorNormal = textColorNormal;
// 重新创建标签
[self resetTagButton];
} - (void)setBackgroundColorSelected:(UIColor *)backgroundColorSelected{ _backgroundColorSelected = backgroundColorSelected;
// 重新创建标签
[self resetTagButton];
} - (void)setBackgroundColorNormal:(UIColor *)backgroundColorNormal{ _backgroundColorNormal = backgroundColorNormal;
// 重新创建标签
[self resetTagButton];
} #pragma mark - Private // 重新创建标签
- (void)resetTagButton{ // 移除之前的标签
for (UIButton* btn in self.subviews) {
[btn removeFromSuperview];
}
// 重新创建标签
[self createTagButton];
} // 创建标签按钮
- (void)createTagButton{ // 按钮高度
CGFloat btnH = ;
// 距离左边距
CGFloat leftX = ;
// 距离上边距
CGFloat topY = ;
// 按钮左右间隙
CGFloat marginX = ;
// 按钮上下间隙
CGFloat marginY = ;
// 文字左右间隙
CGFloat fontMargin = ; for (int i = ; i < _tagArray.count; i++) { UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(marginX + leftX, topY, , btnH);
btn.tag = +i;
// 默认选中第一个
if (i == ) {
btn.selected = YES;
} // 按钮文字
[btn setTitle:_tagArray[i] forState:UIControlStateNormal]; //------ 默认样式
//按钮文字默认样式
NSMutableAttributedString* btnDefaultAttr = [[NSMutableAttributedString alloc]initWithString:btn.titleLabel.text];
// 文字大小
[btnDefaultAttr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:] range:NSMakeRange(, btn.titleLabel.text.length)];
// 默认颜色
[btnDefaultAttr addAttribute:NSForegroundColorAttributeName value:self.textColorNormal range:NSMakeRange(, btn.titleLabel.text.length)];
[btn setAttributedTitle:btnDefaultAttr forState:UIControlStateNormal]; // 默认背景颜色
[btn setBackgroundImage:[self imageWithColor:self.backgroundColorNormal] forState:UIControlStateNormal]; //----- 选中样式
// 选中字体颜色
NSMutableAttributedString* btnSelectedAttr = [[NSMutableAttributedString alloc]initWithString:btn.titleLabel.text];
// 选中颜色
[btnSelectedAttr addAttribute:NSForegroundColorAttributeName value:self.textColorSelected range:NSMakeRange(, btn.titleLabel.text.length)];
// 选中文字大小
[btnSelectedAttr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:] range:NSMakeRange(, btn.titleLabel.text.length)];
[btn setAttributedTitle:btnSelectedAttr forState:UIControlStateSelected]; // 选中背景颜色
[btn setBackgroundImage:[self imageWithColor:self.backgroundColorSelected] forState:UIControlStateSelected]; // 圆角
btn.layer.cornerRadius = btn.frame.size.height / .f;
btn.layer.masksToBounds = YES;
// 边框
btn.layer.borderColor = [UIColor lightGrayColor].CGColor;
btn.layer.borderWidth = 0.5; // 设置按钮的边距、间隙
[self setTagButtonMargin:btn fontMargin:fontMargin]; // 处理换行
if (btn.frame.origin.x + btn.frame.size.width + marginX > self.frame.size.width) {
// 换行
topY += btnH + marginY; // 重置
leftX = ;
btn.frame = CGRectMake(marginX + leftX, topY, , btnH); // 设置按钮的边距、间隙
[self setTagButtonMargin:btn fontMargin:fontMargin];
} // 重置高度
CGRect frame = btn.frame;
frame.size.height = btnH;
btn.frame = frame; //----- 选中事件
[btn addTarget:self action:@selector(selectdButton:) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:btn]; leftX += btn.frame.size.width + marginX;
} // 检测按钮状态,最少选中一个
[self checkButtonState];
} // 设置按钮的边距、间隙
- (void)setTagButtonMargin:(UIButton*)btn fontMargin:(CGFloat)fontMargin{ // 按钮自适应
[btn sizeToFit]; // 重新计算按钮文字左右间隙
CGRect frame = btn.frame;
frame.size.width += fontMargin*;
btn.frame = frame;
} // 检测按钮状态,最少选中一个
- (void)checkButtonState{ int selectCount = ;
UIButton* selectedBtn = nil;
for(int i=;i < _tagArray.count; i++){
UIButton* btn = (UIButton*)[self viewWithTag:+i];
if(btn.selected){
selectCount++;
selectedBtn = btn;
}
}
if (selectCount == ) {
// 只有一个就把这一个给禁用手势
selectedBtn.userInteractionEnabled = NO;
}else{
// 解除禁用手势
for(int i=;i < _tagArray.count; i++){
UIButton* btn = (UIButton*)[self viewWithTag:+i];
if(!btn.userInteractionEnabled){
btn.userInteractionEnabled = YES;
}
}
}
} // 根据颜色生成UIImage
- (UIImage*)imageWithColor:(UIColor*)color{ CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
// 开始画图的上下文
UIGraphicsBeginImageContext(rect.size); // 设置背景颜色
[color set];
// 设置填充区域
UIRectFill(CGRectMake(, , rect.size.width, rect.size.height)); // 返回UIImage
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
// 结束上下文
UIGraphicsEndImageContext();
return image;
} #pragma mark - Event // 标签按钮点击事件
- (void)selectdButton:(UIButton*)btn{ btn.selected = !btn.selected; // 检测按钮状态,最少选中一个
[self checkButtonState];
} @end
好了,大家如果有什么地方看不明白的,留言给我就行~~
IOS动态自适应标签实现的更多相关文章
- jQuery计算文本宽度和input标签根据输入字符动态自适应宽度的实现
jQuery计算文本宽度的原理是利用html提供的<pre>标签,向dom中动态添加<pre>标签,标签里的内容就是要测试长度的文本,获取完长度之后再删除刚才添加的<pr ...
- js 面向对象 动态添加标签
有点逻辑 上代码 thml布局 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...
- EasyUI创建异步树形菜单和动态添加标签页tab
创建异步树形菜单 创建树形菜单的ul标签 <ul class="easyui-tree" id="treeMenu"> </ul> 写j ...
- EasyUI中动态生成标签页
这是最近学到的内容,当时是有思路但是不知道怎么获取当前的点击对象,就没有实现功能,通过更深入的学习,我知道了不仅仅是Java,Oracle中有一个this,同样的EasyUI中也存在一个this,来获 ...
- iOS动态部署方案
转载: iOS动态部署方案 前言 这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容.新的业务流程部署进已发布的App.因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的 ...
- 9.mybatis动态SQL标签的用法
mybatis动态SQL标签的用法 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...
- iframe高度动态自适应
by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1294 一.前言碎碎念 ...
- iOS 键盘自适应(IQKeyboardManager)使用小结
IQKeyboardManager Github地址 经常在开发一个应用程序,我们遇到了一个问题,iPhone的键盘上滑覆盖的UITextField / UITextView.IQKeyboardMa ...
- EasyUI 布局 - 动态添加标签页(Tabs)
首先导入js <link rel="stylesheet" href="../js/easyui/themes/default/easyui.css"&g ...
随机推荐
- atom编辑器快捷键
挑来挑去,还是决定选择atom,做为我的编程编辑器. 下面是我总结的atom快捷键 //1.atomcmd+,; 设置cmd+h; 隐藏程序cmd+alt+h; 隐藏其他程序 //2.文件cmd+n; ...
- [CSS3]学习笔记-文字与字体相关样式
1.给文字添加阴影 <!doctype html> <html> <head> <meta charset="utf-8"> < ...
- [html5] 学习笔记-Canvas 绘制渐变图形与绘制变形图形
在 HTML5 中,使用 Canvas API 绘制图形的知识,可以对绘制图形进行处理,包含使用 Canvas API 绘制渐变图形,使用 Canvas API 的坐标轴变换处理功能绘制变形图形.其中 ...
- iOS 容器控制器 (Container View Controller)
iOS 容器控制器 (Container View Controller) 一个控制器包含其他一个或多个控制器,前者为容器控制器 (Container View Controller),后者为子控制器 ...
- 利用canvas制作乱跑的小球
canvas制作乱跑的小球 说明:将下面的代码放到html的body就可以,键盘控制上(W)下(S)左(A)右(D) <body> <canvas id="canvas&q ...
- CSS3知识点整理(二)----CSS3选择器
总结各种CSS3选择器的介绍及具体语法 (一)属性选择器 在CSS2中引入了一些属性选择器,而CSS3在CSS2的基础上对属性选择器进行了扩展,新增了3个属性选择器,使得属性选择器有了通配符的概念,这 ...
- php抽奖概率算法(刮刮卡,大转盘)
两种方法:①概率随着抽的奖项的变少而时刻变化 经典的概率算法函数:如下 <?php /* * 经典的概率算法, * $proArr是一个预先设置的数组, * 假设数组为:array(20, ...
- layer弹出层中H5播放器全屏出错解决 & 属性poster底图占满<video>的方法
1. 在layer弹窗组件中 如果使用了flash播放器,全屏是正常的 但若使用了HTML5的播放器,全屏失效 举个栗子 <!DOCTYPE html> <html> < ...
- android学习12——重载SurfaceView一些方法的执行顺序
先看代码 public class SurfaceViewActivity extends Activity { @Override public void onCreate(Bundle saved ...
- Socket的应用案例
java提供网络功能的四大类1.InetAddress :用于标识网络上的硬件资源.2.URL:统一资源定位符,通过URL可以直接读取和写入网络上的数据.3.Socket:使用TCP协议实现网络通信的 ...