设计多选按钮ListChooseView

简介:

设计多选按钮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 == 0) {
        NSLog(@"没有一个元素可供选择");
        return;
    }
    
    // 存储所有按钮中文本的宽度
    for (int i = 0; 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 = 0; i < _titleArray.count; i++) {
        [self.allButtonsState addObject:@(NO)];
    }
    
    // 选择按钮列表
    if (self.chosenTitleArray) {
        for (int i = 0; i < self.chosenTitleArray.count; i++) {
            // 获取标题
            NSString *title = self.chosenTitleArray[i];
            
            // 找到匹配的就替换
            for (int j = 0; j < _titleArray.count; j++) {
                if ([_titleArray[j] isEqualToString:title]) {
                    [self.allButtonsState replaceObjectAtIndex:j withObject:@(YES)];
                    break;
                }
            }
        }
    }
    
    // 创建出控件
    CGFloat tmpXpositon = 0;
    for (int i = 0; i < _titleArray.count; i++) {

        CGFloat viewGap = (self.gap == 0 ? 5 : self.gap);
        
        if (i == 0) {
            tmpXpositon += 0;
        } else {
            tmpXpositon += [_buttonWidthArray[i - 1] floatValue] + self.buttonOffset;
        }
        

        // 临时的view,用于存储button
        UIView   *tmpView   = [[UIView alloc] initWithFrame:CGRectMake(0 + i*viewGap + tmpXpositon,
                                                                       0,
                                                                       [_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    = 1; // 显示图片
            } else {
                imageView.alpha    = 0; // 隐藏图片
            }
            
            [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 <= 0 ? 1 : self.lineWidth); // 设置按钮边缘粗细
        if (self.lineColor) {
            tmpButton.layer.borderColor = self.lineColor.CGColor; // 设定线条颜色
        }
        if (self.cornerRadius > 0) {
            tmpButton.layer.cornerRadius = self.cornerRadius; // 设定圆角
        }
    
        [tmpButton addTarget:self
                      action:@selector(buttonsEvent:)
            forControlEvents:UIControlEventTouchUpInside];
        
        // 计算总长度(最后一次循环)
        if (_titleArray.count - 1 == 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        = 0.f;
        }];
    } else {
        UIImageView *tmpView = (UIImageView *)[[button superview] viewWithTag:UIIMAGEVIEW + index];
        [UIView animateWithDuration:0.15 animations:^{
            tmpView.alpha        = 1.f;
        }];
    }
}


/**
 *  计算
 *
 *  @param string 文本
 *  @param font   字体
 *
 *  @return 宽度
 */
- (CGFloat)string:(NSString *)string widthWithLabelFont:(UIFont *)font {
    CGFloat retHeight = 0;
    
    if (string.length == 0) {
        retHeight = 0;
    } else {
        
        // 字体
        NSDictionary *attribute = @{NSFontAttributeName: [UIFont systemFontOfSize:18.f]};
        if (font) {
            attribute = @{NSFontAttributeName: font};
        }
        
        // 尺寸
        CGSize retSize = [string boundingRectWithSize:CGSizeMake(MAXFLOAT, 0)
                                              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(10, 0, 300, 25)];
    chooseView.center           = self.view.center;
    chooseView.buttonOffset     = 20;
    chooseView.gap              = 7.f;
    chooseView.cornerRadius     = 3.f;
    chooseView.buttonFont       = [UIFont systemFontOfSize:14.f];
    chooseView.normalStateButtonTitleColor      = [UIColor grayColor];
    chooseView.highlightedStateButtonTitleColor = [UIColor cyanColor];
    chooseView.lineColor                        = [UIColor grayColor];
    chooseView.selectedImage    = [UIImage imageNamed:@"selected"];
    chooseView.offsetY          = -5;
    chooseView.offsetX          = 10.f;
    chooseView.titleArray       = @[@"女武神", @"瓦尔基里", @"YouXianMing", @"小苹果", @"梦醒时分"];
    chooseView.chosenTitleArray = @[@"YouXianMing"];
    [chooseView createListChooseView];
    
    
    [self.view addSubview:chooseView];
}


@end

需要注意的地方:


目录
相关文章
|
6月前
|
前端开发 JavaScript 开发者
< elementUi 下拉选择框组件 树状部门选择( 多选/单选 )>
在前端开发中,为解决ElementUI缺少处理树状数据选择的Select组件问题,封装了一个Vue子组件`SelectTree`。组件支持单选和多选,具备搜索功能和懒加载特性。单选示例展示了如何展示树状部门数据,而多选则增加了已选内容的取消功能。此外,还新增了根据等级限制选择的功能。文章提供了详细的代码实现和效果截图,对需要此类组件的开发者具有参考价值。
207 1
< elementUi 下拉选择框组件 树状部门选择( 多选/单选 )>
|
6月前
单选全选框如何实现
单选全选框如何实现
40 1
|
前端开发
uniapp checkbox样式失效,选中框选中按钮不显示
uniapp checkbox样式失效,选中框选中按钮不显示
311 0
|
算法 前端开发
下拉选择框
下拉选择框
98 1
|
存储 JavaScript
行内表单 在统一行显示搜索框 下拉框 按钮
行内表单 在统一行显示搜索框 下拉框 按钮
行内表单 在统一行显示搜索框 下拉框 按钮
|
API 数据库
Flutter:使用复选框进行下拉多选
Flutter:使用复选框进行下拉多选 本文向您展示了在 Flutter 中使用复选框实现下拉多选的两种不同方法。在第一种方法中,我们将从头开始构建多选。在第二种方法中,我们将使用第三方包快速完成工作。
735 0
Flutter:使用复选框进行下拉多选