先上效果图

设计要求

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动态自适应标签实现的更多相关文章

  1. jQuery计算文本宽度和input标签根据输入字符动态自适应宽度的实现

    jQuery计算文本宽度的原理是利用html提供的<pre>标签,向dom中动态添加<pre>标签,标签里的内容就是要测试长度的文本,获取完长度之后再删除刚才添加的<pr ...

  2. js 面向对象 动态添加标签

    有点逻辑 上代码 thml布局 点击查看代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  3. EasyUI创建异步树形菜单和动态添加标签页tab

    创建异步树形菜单 创建树形菜单的ul标签 <ul class="easyui-tree" id="treeMenu"> </ul> 写j ...

  4. EasyUI中动态生成标签页

    这是最近学到的内容,当时是有思路但是不知道怎么获取当前的点击对象,就没有实现功能,通过更深入的学习,我知道了不仅仅是Java,Oracle中有一个this,同样的EasyUI中也存在一个this,来获 ...

  5. iOS动态部署方案

    转载: iOS动态部署方案 前言 这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容.新的业务流程部署进已发布的App.因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的 ...

  6. 9.mybatis动态SQL标签的用法

    mybatis动态SQL标签的用法   动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么 ...

  7. iframe高度动态自适应

    by zhangxinxu from http://www.zhangxinxu.com本文地址:http://www.zhangxinxu.com/wordpress/?p=1294 一.前言碎碎念 ...

  8. iOS 键盘自适应(IQKeyboardManager)使用小结

    IQKeyboardManager Github地址 经常在开发一个应用程序,我们遇到了一个问题,iPhone的键盘上滑覆盖的UITextField / UITextView.IQKeyboardMa ...

  9. EasyUI 布局 - 动态添加标签页(Tabs)

    首先导入js <link rel="stylesheet" href="../js/easyui/themes/default/easyui.css"&g ...

随机推荐

  1. 阿里云SSD等磁盘挂载方法(详细步骤完整版)

    1,根据提示购买一块,在阿里云管理磁盘的列表"更多"点击,选中"挂载": 2,进入远程实例(远程系统),管理-->存储-->磁盘管理,在右侧看到新挂 ...

  2. css3 3d变换和动画——回顾

    1.transform-style 属性指定嵌套原始是怎样在三维空间中呈现. 语法:transform-style: flat | preserve-3d flat 表示所有子元素在2D平面呈现. p ...

  3. Jenkins权限配置失误后导致登录失败的解决办法

    为了便于管理,Jenkins一般需要设置用户,而且这些用户是需要配置相应的权限的,如果一不小心配置的时候出了问题,那么,你就斯巴达了. 这里,用我的切身经历,为大家说一下Jenkins因为权限配置失误 ...

  4. 做一个项目前搭建一个tabBar(一)框架

    前言 通常做一个项目前,不算开始讨论需求,分析产品等等,一开始会给我们搭建一个框架,今天简单说一下搭建框架. github网址:https://github.com/Moonths/iWatch.gi ...

  5. java 非缓冲与缓冲数据写入比较

    //非缓冲计时package com.swust; import java.io.*; /* *功能:创建一个程序,写10000个随机双精度的数到一个文件中,同时测试运用缓冲和非缓冲技术 * 进行这种 ...

  6. canvas实例:旋转缩放的方块

    首先在页面中创建一个canvas标签: <body> <canvas id="c1" width="500" height="500 ...

  7. AWT与Swing的区别

    AWT 是Abstract Window ToolKit (抽象窗口工具包)的缩写,这个工具包提供了一套与本地图形界面进行交互的接口.AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的关 ...

  8. Markdown语法收录

    引言 Markdown编辑模式的写法在写博客以及生成简单的页面都有一定的使用,这里只收录Markdown的一些语法供以后查阅使用.具体使用手册可详见Markdown 语法说明(简体中文版) 正文 段落 ...

  9. 安装Apache遇到的一点问题

    很久以前就安装好了Apache(2.2),现在再用时突然出现了问题: 以http://127.0.0.1/exercise/x.php的方式访问文件是正常的,但是要进入phpMyAdmin建表发现不能 ...

  10. Desktop Ubuntu 14.04LTS/16.04科学计算环境配置

    Desktop Ubuntu 14.04LTS/16.04科学计算环境配置 计算机硬件配置 cpu i5 6代 内存容量 8G gpu GTX960 显存容量 2G(建议显存在4G以上,否则一些稍具规 ...