设计多选按钮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. sersync+rsync=实时异步备份

    环境准备 服务器两台 rsync-server:192.168.1.8  (备份服务器) sersync-node1:192.168.1.9 (需要备份的服务器) 系统 CentOS7.4 关闭防火墙 ...

  2. mongodb-mongotemplate进行地理坐标操作

    因为项目中使用的springboot + mongotemplate, 所以还是需要mongotemplate的操作方式 首先建立一个bean: package com.iwhere.easy.tra ...

  3. HTML&&css面试题

    HTML&css相关问题 1.XHTML和HTML有什么区别 HTML是一种基本的WEB网页设计语言,XHTML是一个基于XMl的置标语言 最主要的不同 XHTML元素必须被正确地嵌套. XH ...

  4. ruby中nil?, empty? and blank?的选择

    In Ruby, you check with nil? if an object is nil: article = nil article.nil? # => true empty? che ...

  5. Ubuntu18.0.4查看显示器型号

    在官网https://launchpad.net/ubuntu/+source/xresprobe下载二进制包,apt-get目前无法安装xresprobe 输入命令sudo ddcprobe 得到如 ...

  6. UIKit 框架之Bar、Controller

    UIKit框架中有各种Bar,UITabBar.UINavigationBar.UIToolbar.Bar对应的就有一些Item,tabBarItem.navigationItem.toolbarIt ...

  7. js,需要更多源字符

      里面有的括号没写完 没有关闭 使整个js都不能用 vs2010安装个下面JS插件,更好的分层, https://marketplace.visualstudio.com/items?itemNam ...

  8. 实习小结(五)--- SSM框架搭建(Maven项目)

    之前分享了一个普通的SSM框架的搭建方法,感觉还是过于老套,现在都流行使用Maven来管理项目,在这分享一个使用Maven搭建的SSM(SpringMVC+Spring+MyBatis) 1.首先ma ...

  9. :after伪类+content内容生成经典应用举例——张鑫旭

    一.简单说说content内容生成 content内容生成就是通过content属性生成内容,content属性早在CSS2.1的时候就被引入了,可以使用:before以及:after伪元素生成内容. ...

  10. Unity3D 场景切换加载进度条实现

    需要三个场景,场景A,场景B,场景C: 场景A:一个按钮,点击加载场景B: 场景B:从A切换到C过度场景,加载进度条: 场景C:目标场景: 创建OnProgress.cs脚本: using Syste ...