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 = 28;
 // 距离左边距
 CGFloat leftX = 6;
 // 距离上边距
 CGFloat topY = 10;
 // 按钮左右间隙
 CGFloat marginX = 10;
 // 按钮上下间隙
 CGFloat marginY = 10;
 // 文字左右间隙
 CGFloat fontMargin = 10;

 for (int i = 0; i < _tagArray.count; i++) {

  UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
  btn.frame = CGRectMake(marginX + leftX, topY, 100, btnH);
  btn.tag = 100+i;
  // 默认选中第一个
  if (i == 0) {
   btn.selected = YES;
  }

  // 按钮文字
  [btn setTitle:_tagArray[i] forState:UIControlStateNormal];

  //------ 默认样式
  //按钮文字默认样式
  NSMutableAttributedString* btnDefaultAttr = [[NSMutableAttributedString alloc]initWithString:btn.titleLabel.text];
  // 文字大小
  [btnDefaultAttr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:13] range:NSMakeRange(0, btn.titleLabel.text.length)];
  // 默认颜色
  [btnDefaultAttr addAttribute:NSForegroundColorAttributeName value:self.textColorNormal range:NSMakeRange(0, 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(0, btn.titleLabel.text.length)];
  // 选中文字大小
  [btnSelectedAttr addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:13] range:NSMakeRange(0, btn.titleLabel.text.length)];
  [btn setAttributedTitle:btnSelectedAttr forState:UIControlStateSelected];

  // 选中背景颜色
  [btn setBackgroundImage:[self imageWithColor:self.backgroundColorSelected] forState:UIControlStateSelected];

  // 圆角
  btn.layer.cornerRadius = btn.frame.size.height / 2.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 = 6;
   btn.frame = CGRectMake(marginX + leftX, topY, 100, 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*2;
 btn.frame = frame;
}

// 检测按钮状态,最少选中一个
- (void)checkButtonState{

 int selectCount = 0;
 UIButton* selectedBtn = nil;
 for(int i=0;i < _tagArray.count; i++){
  UIButton* btn = (UIButton*)[self viewWithTag:100+i];
  if(btn.selected){
   selectCount++;
   selectedBtn = btn;
  }
 }
 if (selectCount == 1) {
  // 只有一个就把这一个给禁用手势
  selectedBtn.userInteractionEnabled = NO;
 }else{
  // 解除禁用手势
  for(int i=0;i < _tagArray.count; i++){
   UIButton* btn = (UIButton*)[self viewWithTag:100+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(0, 0, 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

好了,大家如果有什么地方看不明白的,留言给我就行。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • ios动态设置lbl文字标签的高度

    复制代码 代码如下: txtlbl.font = [UIFont boldSystemFontOfSize:14.0f];     txtlbl.numberOfLines = 0;  NSString *str = @"        阿方决定设立科技特网络离开电视剧分w额两个大陆高科技了了不见了日i倒计时离开我说老师肯德基弗兰克萨江东父老将费德勒说阿方决定设立科技特网络离开电视剧分w额两个大陆高科技了了不见了日i倒计时离开我立科说老师肯德基弗兰克萨江东父老将费德勒说";    CG

  • iOS应用开发中UITabBarController标签栏控制器使用进阶

    做了这么长时间的ios开发了,最基本的UITabBarController和UINavigationController都用了好长时间了,总是改现成的代码,或者各种自定义控件的修改,用的都有些混乱了,呵呵.还是自己做个demo再复习一下吧,记录下来以备后续翻查. 一.UITabBarController和UINavigationController的联合使用 这种方法最常见,好像一般有tabbar都会有naviBar.一般使用, 1. 在appDelegate里面创建UITabBarContro

  • iOS 标签Tag列表的实现代码

    前言 1.之前项目中会有一些标签列表来显示某些特性或要求,如下图(代码实现后的效果): 2.期间也是浏览了好多其他的第三方,但是可能是没找到好的方法去寻找吧,没有找到一个合适的,况且又不是特别复杂的东西,所以就自己写了一套,但是注意因为我们项目中使用的是RAC+Mansory,所以想要使用的话需要引入这两个库=_=. 3.自己写的时候考虑的不是太多,中心思想是ViewModel做定制需求,View通过ViewModel来实现定制化UI,其他更多的是逻辑上的排版,所以不做更多赘述,自己体会Y^o^

  • iOS实现顶部标签式导航栏及下拉分类菜单

    本文实例为大家分享了iOS实现顶部标签式导航栏及下拉分类菜单的全部过程,供大家参考,具体内容如下 当内容及分类较多时,往往采用顶部标签式导航栏,例如网易新闻客户端的顶部分类导航,最近刚好有这样的应用场景,参考网络上一些demo,实现了这种导航效果,记录一些要点. 效果图(由于视频转GIF掉帧,滑动和下拉动画显得比较生硬,刚发现quickTime可以直接录制手机视频,推荐一下,很方便) 1.顶部标签式导航栏 (1)实现思路 其实就是在上下两个UIScrollView上做文章,实现联动选择切换的效果

  • iOS仿微信添加标签效果(shape实现)

    一. 概述 可以说微信做的用户体验太棒了,可以做到老少皆宜,给个赞,我们也同时应该告诫自己,用户体验应该向微信看齐,微信就是我们的标杆,那我们今天也来仿一仿微信添加的标签功能.只能仿着做了,真是做不到微信的那种体验.甘拜下风. 我们上篇学习了shape属性的用法,那我们今天就用shape来做下微信的标签功能.先看一下效果. 我不仅用到了shape属性,还用到了翔哥的标签布局FlowLayout跟TagFlowLayout鸿洋的博客 二.效果图 三 .定义shape 添加标签 <?xml vers

  • iOS实现动态自适应标签

    先上效果图  设计要求 1.标签的宽度是按内容自适应的 2.一行显示的标签个数是动态的,放得下就放,放不下就换行 3.默认选中第一个 4.至少选中一个标签 实现思路 首先我们从这个效果上来看,这个标签是有选中和不选中状态,那我们首选的控件肯定就是用 UIButton来实现了. 这个小程度的重点就在于标签能自动换行,还是智能的,不是固定一行多少个那种,这个我们通过计算每个按钮实际宽度与屏幕的宽度进行比较就能判断是否需要换行了. 还有一点就是处理 至少选中一个标签的功能,我这里有一种方式,就是控制按

  • JS脚本实现动态给标签控件添加事件的方法

    本文实例讲述了JS脚本实现动态给标签控件添加事件的方法.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> &l

  • iOS本地动态生成验证码的方法

    前几天app注册被人攻击了,从网上找了这个先保存下.... 用于ios本地动态生成验证码,效果如下: 导入CoreGraphics.framework 用于绘制图形 封装UIView,便捷使用,代码如下: AuthcodeView.h #import <UIKit/UIKit.h> @interface AuthcodeView : UIView @property (strong, nonatomic) NSArray *dataArray;//字符素材数组 @property (stron

  • iOS Runntime 动态添加类方法并调用-class_addMethod

    上手开发 iOS 一段时间后,我发现并不能只着眼于完成需求,利用闲暇之余多研究其他的开发技巧,才能在有限时间内提升自己水平.当然,"其他开发技巧"这个命题对于任何一个开发领域都感觉不找边际,而对于我来说,尝试接触 objc/runtime 不失为是开始深入探索 iOS 开发的第一步. 刚了解 runtime 当然要从比较简单的 api 开始,今天就罗列整理一下 class_addMethod 的相关点: 首先从文档开始. /** * Adds a new method to a cla

  • iOS实现动态的开屏广告示例代码

    一.实现效果图 二.实现思路: 用一个固定的png图片左启动图,应该和广告视图需要进行动画的期初的位置一致,当启动图消失的时候,呈现出图片,实际遇到的困难是,因为广告图片是从网络请求加载的,当时把广告视图放在了请求数据的块里面,广告出现的时候会闪一下,放在外面就没事了. 三.实现示例 1.广告的头文件 // XBAdvertView.h // scoreCount // // Created by 王国栋 on 15/12/22. // Copyright © 2015年 xiaobai. Al

  • JS实现动态给标签控件添加事件的方法示例

    本文实例讲述了JS实现动态给标签控件添加事件的方法.分享给大家供大家参考,具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <

  • jQuery 动态云标签插件

    前言: 最近对js的插件封装特别感兴趣,无耐就目前的技术想做到js的完全封装,还是有一定困难,就基于jQuery封装了一个小的插件,而且是基于对象级开发的,不是添加全局方法.高深的语法几乎没有,就有一个return:foreach()方法来返回对象实例本身,还有一个extend()函数,用来扩展参数对象的属性,这也是为了对象在调完我这个方法后方便链式操作. 插件打包下载地址:点我下载 插件名:动态云标签 插件特点: 在指定块级元素内动态生成a标签 a标签的高度.宽度.位置.层数.背景颜色随机可控

  • javascript的document中的动态添加标签实现方法

    document的高级篇中提供了节点操作的函数,具体包括:获取节点,改变节点,删除节点,替换节点,创建节点,添加节点,克隆节点等函数.我们可以利用这些函数动态改变html的节点. 1.JavaScript <script type="text/javascript"> function test1(){//对个节点的ID相同时候的情况 var myhref = document.getElementById('same'); window.alert(myhref.inne

  • MyBatis使用动态SQL标签的小陷阱

    MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 现在MyBatis越来越受大家的喜爱了,它的优势大家都知道,我就不多说了,直接说重点. MyBatis中提供动态SQL功能,我们可以使用<if><when&

随机推荐