设计多选按钮ListChooseView

答应某位女屌丝而写的控件,效果还不错,开源给大家^_^!

效果图:

源码:

//
// ListChooseView.h
// ScrollChooseButton
//
// http://www.jikexueyuan.com/course/397.html
// http://www.cnblogs.com/YouXianMing/
//
// Created by YouXianMing on 14/12/23.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
// #import <UIKit/UIKit.h> @interface ListChooseView : UIView #pragma mark -
/**
* 按钮之间的间隙,不设置的话默认值为5
*/
@property (nonatomic, assign) CGFloat gap; /**
* 按钮值偏移量
*/
@property (nonatomic, assign) CGFloat buttonOffset; #pragma mark -
/**
* 标题数组
*/
@property (nonatomic, strong) NSArray *titleArray; /**
* 已经选择的标题的数组
*/
@property (nonatomic, strong) NSArray *chosenTitleArray; #pragma mark -
/**
* 按钮的字体
* 正常状态下的按钮色值(不设定则为白色)
* 高亮状态下的按钮色值(不设定则没有值)
* 按钮线条粗细(不设定默认值为1)
* 按钮线条颜色(不设定默认值为黑色)
* 按钮圆角
*/
@property (nonatomic, strong) UIFont *buttonFont;
@property (nonatomic, strong) UIColor *normalStateButtonTitleColor;
@property (nonatomic, strong) UIColor *highlightedStateButtonTitleColor;
@property (nonatomic, assign) CGFloat lineWidth;
@property (nonatomic, strong) UIColor *lineColor;
@property (nonatomic, assign) CGFloat cornerRadius; #pragma mark -
/**
* 选中状态下显示的图片
* 图片横线偏移量
* 图片纵向偏移量
*/
@property (nonatomic, strong) UIImage *selectedImage;
@property (nonatomic, assign) CGFloat offsetX;
@property (nonatomic, assign) CGFloat offsetY; #pragma mark - /**
* 选中的标题
*/
@property (nonatomic, strong, readonly) NSMutableArray *selectedIndex; /**
* 配置好所有参数后就创建出控件
*/
- (void)createListChooseView; @end
//
// ListChooseView.m
// ScrollChooseButton
//
// Created by YouXianMing on 14/12/23.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
// #import "ListChooseView.h" typedef enum : NSUInteger {
UIBUTTON = 0x19871220, // [YouXingMing birthDay]
UIIMAGEVIEW = 0x88888888,
} EnumListChooseView; @interface ListChooseView () @property (nonatomic, assign) CGFloat buttonHeight; // 按钮的高度
@property (nonatomic, assign) CGFloat totalLength; // 总长度 @property (nonatomic, strong) UIScrollView *scrollView; // 用于滑动的scrollView
@property (nonatomic, strong) NSMutableArray *buttonWidthArray; // 存储所有按钮的宽度 @property (nonatomic, strong) NSMutableArray *allButtonsState; // 存储所有按钮点击状态
@property (nonatomic, strong) NSMutableArray *selectedIndex; @end @implementation ListChooseView - (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// 添加scrollView
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.layer.masksToBounds = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
[self addSubview:_scrollView]; // 按钮高度
_buttonHeight = frame.size.height; // 存储所有按钮宽度
_buttonWidthArray = [NSMutableArray array];
}
return self;
} - (void)createListChooseView {
// 没有一个元素则直接返回
if (_titleArray.count == ) {
NSLog(@"没有一个元素可供选择");
return;
} // 存储所有按钮中文本的宽度
for (int i = ; i < _titleArray.count; i++) {
// 必须是字符串
if ([_titleArray[i] isKindOfClass:[NSString class]]) {
CGFloat buttonWidth = [self string:_titleArray[i] widthWithLabelFont:self.buttonFont];
[_buttonWidthArray addObject:@(buttonWidth)];
} else {
NSLog(@"有非字符串的东西混入");
return;
}
} // 所有按钮点击状态初始化(默认为NO,没有勾选)
self.allButtonsState = [NSMutableArray array];
for (int i = ; i < _titleArray.count; i++) {
[self.allButtonsState addObject:@(NO)];
} // 选择按钮列表
if (self.chosenTitleArray) {
for (int i = ; i < self.chosenTitleArray.count; i++) {
// 获取标题
NSString *title = self.chosenTitleArray[i]; // 找到匹配的就替换
for (int j = ; j < _titleArray.count; j++) {
if ([_titleArray[j] isEqualToString:title]) {
[self.allButtonsState replaceObjectAtIndex:j withObject:@(YES)];
break;
}
}
}
} // 创建出控件
CGFloat tmpXpositon = ;
for (int i = ; i < _titleArray.count; i++) { CGFloat viewGap = (self.gap == ? : self.gap); if (i == ) {
tmpXpositon += ;
} else {
tmpXpositon += [_buttonWidthArray[i - ] floatValue] + self.buttonOffset;
} // 临时的view,用于存储button
UIView *tmpView = [[UIView alloc] initWithFrame:CGRectMake( + i*viewGap + tmpXpositon,
,
[_buttonWidthArray[i] floatValue] + self.buttonOffset,
_buttonHeight)];
// 配置button
UIButton *tmpButton = [[UIButton alloc] initWithFrame:tmpView.bounds];
[tmpView addSubview:tmpButton]; // 按钮tag值
tmpButton.tag = UIBUTTON + i; if (self.selectedImage) { // 添加选中的图片
UIImageView *imageView = [[UIImageView alloc] initWithImage:self.selectedImage]; CGRect rect = imageView.frame;
rect.origin.x = [_buttonWidthArray[i] floatValue] + self.offsetX;
rect.origin.y = self.offsetY;
imageView.frame = rect; imageView.tag = UIIMAGEVIEW + i;
if ([self.allButtonsState[i] boolValue] == YES) {
imageView.alpha = ; // 显示图片
} else {
imageView.alpha = ; // 隐藏图片
} [tmpView addSubview:imageView];
}
[tmpButton setTitle:_titleArray[i] forState:UIControlStateNormal]; // 设置标题
if (self.buttonFont) {
tmpButton.titleLabel.font = self.buttonFont; // 设置按钮字体
}
if (self.normalStateButtonTitleColor) {
[tmpButton setTitleColor:self.normalStateButtonTitleColor forState:UIControlStateNormal]; // 设置按钮正常标题颜色
}
if (self.highlightedStateButtonTitleColor) {
[tmpButton setTitleColor:self.highlightedStateButtonTitleColor forState:UIControlStateHighlighted]; // 高亮标题颜色
}
tmpButton.layer.borderWidth = (self.lineWidth <= ? : self.lineWidth); // 设置按钮边缘粗细
if (self.lineColor) {
tmpButton.layer.borderColor = self.lineColor.CGColor; // 设定线条颜色
}
if (self.cornerRadius > ) {
tmpButton.layer.cornerRadius = self.cornerRadius; // 设定圆角
} [tmpButton addTarget:self
action:@selector(buttonsEvent:)
forControlEvents:UIControlEventTouchUpInside]; // 计算总长度(最后一次循环)
if (_titleArray.count - == i) {
_totalLength = tmpView.frame.origin.x + [_buttonWidthArray[i] floatValue] + self.buttonOffset;
} [self.scrollView addSubview:tmpView];
} self.scrollView.contentSize = CGSizeMake(_totalLength, _buttonHeight);
} - (void)buttonsEvent:(UIButton *)button { // 第几个按钮
NSInteger index = button.tag - UIBUTTON;
BOOL selectedButtonState = [_allButtonsState[index] boolValue];
[_allButtonsState replaceObjectAtIndex:index withObject:@(!selectedButtonState)]; // 选择了几个按钮
self.selectedIndex = [NSMutableArray arrayWithArray:_allButtonsState]; // 更新按钮上面的图标
[self updateButtonImage:button index:index];
} - (void)updateButtonImage:(UIButton *)button index:(NSInteger)index{
if ([_allButtonsState[index] boolValue] == NO) {
UIImageView *tmpView = (UIImageView *)[[button superview] viewWithTag:UIIMAGEVIEW + index];
[UIView animateWithDuration:0.15 animations:^{
tmpView.alpha = .f;
}];
} else {
UIImageView *tmpView = (UIImageView *)[[button superview] viewWithTag:UIIMAGEVIEW + index];
[UIView animateWithDuration:0.15 animations:^{
tmpView.alpha = .f;
}];
}
} /**
* 计算
*
* @param string 文本
* @param font 字体
*
* @return 宽度
*/
- (CGFloat)string:(NSString *)string widthWithLabelFont:(UIFont *)font {
CGFloat retHeight = ; if (string.length == ) {
retHeight = ;
} else { // 字体
NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:.f]};
if (font) {
attribute = @{NSFontAttributeName: font};
} // 尺寸
CGSize retSize = [string boundingRectWithSize:CGSizeMake(MAXFLOAT, )
options:
NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:attribute
context:nil].size; retHeight = retSize.width;
} return retHeight;
} @end

使用时候的源码:

//
// ViewController.m
// ScrollChooseButton
//
// Created by YouXianMing on 14/12/23.
// Copyright (c) 2014年 YouXianMing. All rights reserved.
// #import "ViewController.h"
#import "ListChooseView.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad]; self.view.backgroundColor = [UIColor blackColor]; [self createListChooseView];
} - (void)createListChooseView {
ListChooseView *chooseView = [[ListChooseView alloc] initWithFrame:CGRectMake(, , , )];
chooseView.center = self.view.center;
chooseView.buttonOffset = ;
chooseView.gap = .f;
chooseView.cornerRadius = .f;
chooseView.buttonFont = [UIFont systemFontOfSize:.f];
chooseView.normalStateButtonTitleColor = [UIColor grayColor];
chooseView.highlightedStateButtonTitleColor = [UIColor cyanColor];
chooseView.lineColor = [UIColor grayColor];
chooseView.selectedImage = [UIImage imageNamed:@"selected"];
chooseView.offsetY = -;
chooseView.offsetX = .f;
chooseView.titleArray = @[@"女武神", @"瓦尔基里", @"YouXianMing", @"小苹果", @"梦醒时分"];
chooseView.chosenTitleArray = @[@"YouXianMing"];
[chooseView createListChooseView]; [self.view addSubview:chooseView];
} @end

需要注意的地方:

设计多选按钮ListChooseView的更多相关文章

  1. .NET开源工作流RoadFlow-表单设计-复选按钮组

    复选按钮组的设置与单选按钮组的设置相同,只是表现形式为:<input type="checkbox"/>

  2. 设计多选一按钮ChooseOnlyButton

    设计多选一按钮ChooseOnlyButton 效果: 源码: ChooseOnlyButton.h 与 ChooseOnlyButton.m // // ChooseOnlyButton.h // ...

  3. js动态获取子复选项并设计全选及提交

    在做项目的时候,会遇到根据父选项,动态的获取子选项,并列出多个复选框,提交时,把选中的合并成一个字符提交后台 本章将讲述如何通过js控制实现该操作: 1:设计父类别为radio,为每一个radio都加 ...

  4. Chapter 4. Button, Checkbutton, and Radiobutton Widgets 按钮,复选按钮,单选按钮

    Chapter 4. Button, Checkbutton, and Radiobutton Widgets   按钮,复选按钮,单选按钮 几乎所有的Perl/Tk 应用使用按钮以这样或者那样的方式 ...

  5. 单选按钮、复选按钮——axure线框图部件库介绍

    有时候发现这做事情坚持下来是一件很不容易的,写教程也一样,不过听到很多朋友对我说 这个全部是图片的教程 对他们入门帮助很多,我就想想 在坚持坚持把基础部分先完善了! 1. 简单的问卷调查: 您的性别? ...

  6. 《手把手教你》系列技巧篇(三十三)-java+ selenium自动化测试-单选和多选按钮操作-上篇(详解教程)

    1.简介 在实际自动化测试过程中,我们同样也避免不了会遇到单选和多选的测试,特别是调查问卷或者是答题系统中会经常碰到.因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助 ...

  7. 《手把手教你》系列技巧篇(三十四)-java+ selenium自动化测试-单选和多选按钮操作-中篇(详解教程)

    1.简介 今天这一篇宏哥主要是讲解一下,如何使用list容器来遍历单选按钮.大致两部分内容:一部分是宏哥在本地弄的一个小demo,另一部分,宏哥是利用JQueryUI网站里的单选按钮进行实战. 2.d ...

  8. 《手把手教你》系列技巧篇(三十五)-java+ selenium自动化测试-单选和多选按钮操作-下篇(详解教程)

    1.简介 今天这一篇宏哥主要是讲解一下,如何使用list容器来遍历多选按钮.大致两部分内容:一部分是宏哥在本地弄的一个小demo,另一部分,宏哥是利用JQueryUI网站里的多选按钮进行实战. 2.d ...

  9. 《手把手教你》系列技巧篇(三十六)-java+ selenium自动化测试-单选和多选按钮操作-番外篇(详解教程)

    1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何自动化测试,这一篇宏哥在网上找了一个问卷调查,给小伙伴或童鞋们来演示一下.上 ...

随机推荐

  1. Go 压测

    1. 单测 + 压测 压测 go test -bench=. -benchmem 单元测试 go test -v . 2. pprof + 火焰图(查看cpu占用,内存占用) 嵌入代码 import ...

  2. 反转ListBox的ListBoxItem(控件级别,不是数据的反转)

    在默认的排序下,当将ListBoxItem往下移动时,ListBoxItem是从其他ListBoxItem的底部移动的如下图:   但当往上移动时,情况则不是如此,     所以需要尝试对ListBo ...

  3. cordova打包APK,报错:Cannot evaluate module CordovaLib : Configuration with name 'debug' not found.

    原因:之前做其他项目的时候把环境(gradle)升级了. 解决方案:将gradle降低回原来的版本.

  4. VS中调试查看DataTable和DataSet时未能加载此自定义查看器解决方法

    在网上找了几个方法,感觉不太实用,最后自己找到了问题所在  VS2017中选择调试-选项-常规中的使用托管兼容模式取消勾选.之后就可以了

  5. 微信小程序: 编译.wxss文件错误解决

    博主最近又重新开始捡起微信小程序,想做点自己的东西.了解到最近小程序工具有做更新,就顺手更新了最新的版本,功能比之前强大了不少!  更新归更新,更新后控制台就一直报下面这个错误:  解决办法 有问题总 ...

  6. emberjs 按年月分组

    一个集合,里面有年和月的属性,按照年和月进行分组显示数据 + item.TopicMonth }).map(function (value, key) { return { time: { year: ...

  7. [日常] PHP设置 include_path 配置选项

    动态设置php.ini中的include_path 配置选项: 两种方式set_include_path($new_include_path)ini_set('include_path',$new_i ...

  8. 数组的strong copy理解

      一.数组的不同情况下的copy,mutablecopy分析 1.不可变数组的copy(没有创建新对象,复制的只是指针)       2.不可变数组的mutable copy(创建新对象)     ...

  9. 设置navigationbar透明度时的坑

    1.需要设置导航条透明度时     UIImage *image = [UIImage imageNamed:@"bg_clear.png"]; //设置背景颜色 [nav2.na ...

  10. Netty面试

    声明:此文章非本人所 原创,是别人分享所得,如有知道原作者是谁可以联系本人,如有转载请加上此段话  1.BIO.NIO 和 AIO 的区别? BIO:一个连接一个线程,客户端有连接请求时服务器端就需要 ...