这是一个封装好的类TagListView,

1. 只需要调用两个方法 设置宽度,间距,边距 并赋给它需要显示的字符串数组;

2. 遵循tagListView的协议, 并实现返回buttonView的方法.

即可展现.

这里我用了SDAutoLayout, 一个三方布局, 用cocopod安装一下就好;

一下是具体的实现代码 带 注释解释

//  TagListView.h 该类的.h文件

#import <UIKit/UIKit.h>
@protocol TagListViewDelegate<NSObject>
@required
- (UIButton *)setItemBtnView; //必须实现方法:返回buttonView
@optional
- (void)clickWithBtn:(UIButton *)btn idx:(NSInteger)idx; //点击button触发方法
@end typedef void(^ReturnClickBtnArr)(NSArray *btnArr); // 返回已选中的按钮数组 @interface TagListView : UIView @property(nonatomic, strong) UIButton *itemBtn;
@property(nonatomic, assign) NSUInteger maxSelectedTags; // 多选值
@property(nonatomic, strong) NSMutableArray *selectedTitles; //已选中的按钮标题数组
@property(nonatomic, weak) id <TagListViewDelegate> delegate; #pragma mark - 设置宽度 间距 边距
- (void)setWid:(CGFloat)wid btnTitlePadding_X:(CGFloat)horizontailX btnTitlePadding_Y:(CGFloat)vertailY marginX:(CGFloat)marginX marginY:(CGFloat)marginY itemHeight:(CGFloat)height; #pragma mark - 设置字符串数组 (该方法必须在setWid...方法后执行)
- (void)setTagViewWithTitles:(NSArray *)titleArr; - (NSArray *)getAllSubBtns;
@end
//  TagListView.m 该类的.m文件

#import "TagListView.h"
#import "UIView+SDAutoLayout.h"
#define kHorizontalX 7
#define kVerticalY 3
#define kMarginY 10
#define kMarginX 10 @implementation TagListView {
CGFloat _horizontailX; // btn的左右间距
CGFloat _vertailY; // btn的上下间距
CGFloat _marginX; // tagView的左右边距
CGFloat _marginY; // tagVIew的上下边距
CGFloat _wid; // tagView的宽度
CGFloat _itemHeight; // btn的高度
NSArray *_titleArray; // 需要展示的字符串数组
} - (instancetype)init {
if (self = [super init]) {
_horizontailX = kHorizontalX;
_vertailY = kVerticalY;
_marginX = kMarginY;
_marginY = kMarginX;
_wid = ;
_maxSelectedTags = ; //default
_selectedTitles = [NSMutableArray array];
}
return self;
} #pragma mark - 设置宽度 间距 边距
- (void)setWid:(CGFloat)wid btnTitlePadding_X:(CGFloat)horizontailX btnTitlePadding_Y:(CGFloat)vertailY marginX:(CGFloat)marginX marginY:(CGFloat)marginY itemHeight:(CGFloat)height {
if (wid) {
_wid = wid;
}
if (horizontailX) {
_horizontailX = horizontailX;
}
if (vertailY) {
_vertailY = vertailY;
}
if (marginX) {
_marginX = marginX;
}
if (marginY) {
_marginY = marginY;
}
if (height) {
_itemHeight = height;
}
} #pragma mark - 设置字符串数组 (该方法必须在setWid...方法后执行)
- (void)setTagViewWithTitles:(NSArray *)titleArr {
_titleArray = [titleArr copy]; // 清除所有子视图
while (self.subviews.count) {
UIView *child = self.subviews.lastObject;
[child removeFromSuperview];
} // 若未指定宽度 就 获得当前视图宽度
if (_wid == ) {
[self updateLayout];
_wid = self.width;
} __block int totalHeight = ;
__block CGRect previousFrame = CGRectMake(, , , );
__block CGFloat height = ; // 循环title数组
[titleArr enumerateObjectsUsingBlock:^(NSString *title, NSUInteger idx, BOOL * _Nonnull stop) {
UIButton *tag = [self.delegate setItemBtnView];
[tag setTitle:title forState:UIControlStateNormal];
[tag addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
tag.tag = idx; // 设置已选中title的选中状态
if ([self.selectedTitles containsObject:title]) {
tag.selected = YES;
} else {
tag.selected = NO;
} // 1. 计算size
// 获得title字体对应的size
NSDictionary *attrs = @{NSFontAttributeName : tag.titleLabel.font};
CGSize Size_str = [title sizeWithAttributes:attrs]; // 给size加上 上下边距
Size_str.width += _horizontailX * ;
if (_itemHeight) {
Size_str.height = _itemHeight;
} else {
Size_str.height += _vertailY * ;
} CGRect newRect = CGRectZero;
newRect.size = Size_str;
// 2. 计算origin
if (CGRectGetMaxX(previousFrame) + Size_str.width + _marginX > _wid) { //换行
newRect.origin = CGPointMake(, CGRectGetMaxY(previousFrame) + _marginY);
totalHeight += Size_str.height + _marginY;
} else { //未换行
newRect.origin = CGPointMake((CGRectGetMaxX(previousFrame) == ? : CGRectGetMaxX(previousFrame) + _marginX), previousFrame.origin.y);
}
[tag setFrame:newRect]; previousFrame = tag.frame;
height = totalHeight + Size_str.height; [self addSubview:tag];
}]; self.sd_layout.heightIs(height);
} - (NSArray *)getAllSubBtns {
return self.subviews;
} #pragma mark - btn的点击方法
- (void)onClick:(UIButton *)btn {
// 1.如果超出最多选中数 则需把最先选中的删除
if (!btn.selected && self.selectedTitles.count >= _maxSelectedTags){
NSString *title = [self.selectedTitles objectAtIndex:];
NSUInteger firstSelectedIndex = [_titleArray indexOfObject:title];
if (firstSelectedIndex != NSNotFound) {
UIButton *selectedButton = [self.subviews objectAtIndex:firstSelectedIndex];
selectedButton.selected = NO;
[self.selectedTitles removeObjectAtIndex:];
}
}
long index = btn.tag;
NSString *title = [_titleArray objectAtIndex:index];
if (btn.selected) { // 设置为未选中状态
btn.selected = NO;
[self.selectedTitles removeObject:title];
} else { // 设置为选中状态
btn.selected = YES;
[self.selectedTitles addObject:title];
}
// 若delegate包含该方法 则让其执行
if ([self.delegate respondsToSelector:@selector(clickWithBtn:idx:)]) {
[self.delegate clickWithBtn:btn idx:index];
}
}
@end

具体使用如下:

//  ViewController.m

#import "ViewController.h"
#import "UIView+SDAutoLayout.h"
#import "TagListView.h" #define kScreenWidth self.view.frame.size.width @interface ViewController ()<TagListViewDelegate>
@property (nonatomic, strong)TagListView *tagListView;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; self.tagListView = [[TagListView alloc] init];
self.tagListView.delegate = self;
self.tagListView.backgroundColor = [UIColor cyanColor];
self.tagListView.maxSelectedTags = ;
[self.view addSubview:self.tagListView];
self.tagListView.sd_layout.topSpaceToView(self.view, ).leftSpaceToView(self.view, ).rightSpaceToView(self.view, );
// 设置宽度 间距 边距
[self.tagListView setWid:(kScreenWidth - ) btnTitlePadding_X: btnTitlePadding_Y: marginX: marginY: itemHeight:];
// 设置需要显示的字符串数组
[self.tagListView setTagViewWithTitles:@[@"周一", @"周二", @"周三", @"周四", @"周五", @"礼拜六", @"礼拜天", @"一月", @"二月", @"三月", @"四月", @"五月", @"六月", @"七月", @"八月", @"九月", @"十月", @"十一月", @"十二月", @"春天", @"夏天", @"秋天", @"冬天", @"张三", @"李四", @"王五"]];
} #pragma mark - TagListViewDelegate
// 必须实现的协议方法 返回buttonView
- (UIButton *)setItemBtnView {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
btn.layer.borderWidth = 0.4;
btn.layer.cornerRadius = ;
btn.layer.borderColor = [UIColor grayColor].CGColor;
return btn;
} @end

button自适应宽度 并根据屏幕宽自动换行排列的更多相关文章

  1. 【笔记】css 实现宽度自适应屏幕 高度自适应宽度

    如果说宽高自适应屏幕尺寸那么大家可能会想到 div{ width: 100%; height: 100% } 但是如果我要自适应屏幕尺寸的同时还要变成正方形呢?(高度和宽度相等而高度不能写死) 那就要 ...

  2. 解决Button在IE6、7下的自适应宽度问题

    很早就遇到过这么个小问题,但由于其并未影响到实际作用和美观就没有正面解决它,现在,我们来试着解决它. 写一个Button,有两种方式:其一,直接button标签:其二,input type=”butt ...

  3. 从三栏自适应宽度布局到css布局的讨论

    如何实现一个三栏自适应布局,左右各100px,中间随着浏览器宽度自适应? 第一个想到的是使用table布局,设置table的宽度为100%,三个td,第1个和第3个固定宽度为100px,那么中间那个就 ...

  4. [Winform]DataGridView列自适应宽度

    引言 在做winform项目中,数据控件DataGridView的使用多多少少是会用到的,如果不设置它的属性,默认情况下是不会自适应宽度的,你想查看某项的数据,就不得不将标题栏拖来拖去,挺烦的. 方法 ...

  5. android屏幕适配的全攻略3-动态获取手机屏幕宽高及动态设置控件宽高

    1.获取手机屏幕宽高: DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetr ...

  6. UEditor百度富文本编辑器--让编辑器自适应宽度的解决方案

    UEditor百度富文本编辑器的initialFrameWidth属性,默认值是1000. 不能够自适应屏幕宽度.如图1: 刚开始的时候,我是直接设置initialFrameWidth=null的.效 ...

  7. JS 获取浏览器和屏幕宽高等信息代码

    JS 获取浏览器和屏幕宽高等信息. 网页可见区域宽:document.body.clientWidth  网页可见区域高:document.body.clientHeight  网页可见区域宽:doc ...

  8. 漂亮的自适应宽度的多色彩CSS图片按钮

    一.素材               二.效果 三.CSS *{padding:0;margin:0} /*----------------------------------- 自适应宽度图片按钮 ...

  9. Android编程心得-在任意类中获取当前屏幕宽高

    进行Android编程时,很多时候都需要获取当前屏幕的宽度与高度,但是当我们需要在别的类中调用屏幕宽高时,直接用原来的方法是不行的,下面我来介绍如何在任意类中调用宽度高度的两种方法. public v ...

随机推荐

  1. 从零开始,DIY一个jQuery(1)

    从本篇开始会陪大家一起从零开始走一遍 jQuery 的奇妙旅途,在整个系列的实践中,我们会把 jQuery 的主要功能模块都了解和实现一遍. 这会是一段很长的历程,但也会很有意思 —— 作为前端领域的 ...

  2. C#与C++的发展历程第一 - 由C#3.0起

    俗话说学以致用,本系列的出发点就在于总结C#和C++的一些新特性,并给出实例说明这些新特性的使用场景.前几篇文章将以C#的新特性为纲领,并同时介绍C++中相似的功能的新特性,最后一篇文章将总结之前几篇 ...

  3. ABP框架 - 多层结构

    文档目录 本节内容: 简介 ABP结构 多层 其它层(通用) 领域(Core)层 应用层 基础层 Web & 表示层 其它 总结 简介 一个应用的代码库的分层是一个广为接受的技术,用来减少复杂 ...

  4. Java 8函数编程轻松入门(三)默认方法详解(default function)

    default出现的原因 Java 8中对API最大的改变在于集合类,Java在持续演进,但是它一直保持着向后兼容. 在Java 8中为Collection接口增加了stream方法,这意味着所有实现 ...

  5. C# BS消息推送 负载均衡-SignalR&Redis的配置(三)

    1. 前言 本文是根据网上前人的总结得出的. 环境: SignalR2.x,VS2015,Win10 2. 负载均衡配置 配置很简单,只要在startup类中添加Redis的连接就OK. 1)首先,引 ...

  6. 【Win10 应用开发】自定义应用标题栏

    Win 10 app对窗口标题栏的自定义包括两个层面:一是只定义标题中各部分的颜色,如标题栏上文本的颜色.三个系统按钮(最大化,最小化,关闭)的背景颜色等:另一层是把窗口的可视区域直接扩展到标题栏上, ...

  7. Angular Service入门

    1.Angular内置service Angular为了方便开发者开发,本身提供了非常多的内置服务.可以通过https://docs.angularjs.org/api/ng/service查看Ang ...

  8. Hawk 4.2 过滤器

    过滤器可以在流中,过滤掉不符合条件的文档.当然也可勾选反向,此时只会留下不符合条件的文档. 空对象过滤器 最为常用,需要列名,可以过滤掉所有内容为Null,或字符串全部都是空字符的情况 数值范围过滤 ...

  9. 移动端web开发的那些坑

    1.为非a列表项添加触感样式 通过js注册touchstart和touchend事件,添加触感class的方式, 有个坑,低版本的Android浏览器,经常触发不到touchend,需要再额外注册一个 ...

  10. heart

    好久没写博客了,不想废话,直接欣赏效果! 点击这里,查看完美效果! 附完整代码: <!doctype html> <html> <head> <meta ch ...