iOS开发系列之常用自定义控件开发集—自定义组按钮控件开发

在开发中经常有需求要求创建一排按钮,下面我们就开发这一个组件,实现方式如下:
WHC_ButtonGroupView.h头文件如下:

//
//  buttonGroupView.h
//  buttonGroupView
//
//  Created by 吴海超 on 14-6-6.
//  Copyright (c) 2014年 buttonGroupView. All rights reserved.
//


/*
 NOTE:获取组按钮默认创建实现方式如下:
 +(WHC_ButtonGroupParam *)getDefaultParamWithTitleArr:(NSArray*)titleArr{
     WHC_ButtonGroupParam * groupParam = [WHC_ButtonGroupParam new];
     groupParam.normalBackColor      = [UIColor grayColor];
     groupParam.selectedBackColor    = [UIColor blackColor];
     groupParam.markColor            = [UIColor clearColor];
     groupParam.segmentLineY         = 0.0;
     groupParam.segmentLineColor     = [UIColor blackColor];
     groupParam.normalTextColor      = [UIColor whiteColor];
     groupParam.selectedTextColor    = [UIColor grayColor];
     groupParam.titles               = titleArr;
     groupParam.images               = nil;
     groupParam.scroll               = NO;
     groupParam.headLine             = YES;
     groupParam.footLine             = YES;
     groupParam.firstSegmentLine     = YES;
     groupParam.markViewDown         = NO;
     groupParam.fontSize             = 16.0;
     groupParam.markPading           = 5.0;
     return groupParam;
 }

 */

#import <UIKit/UIKit.h>
@class WHC_ButtonGroupView;
@protocol  WHC_ButtonGroupViewDelegate<NSObject>

@required
- (void)whcButtonGroup:(WHC_ButtonGroupView*)whcBtnView index:(NSInteger)index;
@end

@interface WHC_ButtonGroupParam : NSObject
@property BOOL    scroll;                      //是否支持滚动
@property BOOL    footLine;                    //是否显示底部线
@property BOOL    headLine;                    //是否显示顶部线
@property BOOL    markViewDown;                //是否下标记
@property BOOL    firstSegmentLine;            //首部分割线
@property int     currIndex;                   //当前下标
@property CGFloat fontSize;                    //字体大小
@property CGFloat btnHeight;                   //按钮高度
@property CGFloat btnWidth;                    //按钮宽度
@property CGFloat markPading;                  //游标和按钮的间隙
@property CGFloat segmentLineY;                //分隔线Y坐标
@property CGFloat scrollWidth;                 //滚条宽度
@property UIColor *normalBackColor;            //默认按钮背景颜色
@property UIColor *selectedBackColor;          //选中按钮背景颜色
@property UIColor *normalTextColor;            //默认状态按钮文字颜色
@property UIColor *selectedTextColor;          //选中状态按钮文字颜色
@property UIColor *segmentLineColor;           //分隔线颜色
@property UIColor *markColor;                  //移动游标颜色
@property NSArray *titles;                     //按钮标题
@property NSArray *images;                     //按钮图片

+ (WHC_ButtonGroupParam *)getDefaultParamWithTitleArr:(NSArray*)titleArr;      //获取默认参数
@end

@interface WHC_ButtonGroupView : UIView
@property id<WHC_ButtonGroupViewDelegate> delegate;
- (void)changeSelectedStateButtonWithIndex:(NSInteger)index;                   //改变指定按钮的状态

- (BOOL)deleteButtonWithIndex:(NSInteger)index withTitle:(NSString*)title;     //删除指定按钮

- (BOOL)addButtonWithIndex:(NSInteger)index withTitle:(NSString*)title;        //添加按钮到指定位子

- (void)switchUIOrientationWithIsHori:(BOOL)isHori withPading:(CGFloat)pad;    //转换屏幕处理

- (id)initWithFrame:(CGRect)frame withParam:(WHC_ButtonGroupParam*)param;     //初始化

- (void)gotoOtherBtnOptionWithIndex:(NSInteger)index;                          //切换到其他按钮响应

- (void)modifyButtonTitleForIndex:(NSInteger)index withTitle:(NSString*)title; //修改指定按钮标题
@end

WHC_ButtonGroupView.m源文件如下:

//
//  buttonGroupView.m
//  bhtrader
//
//  Created by apple on 14-6-6.
//  Copyright (c) 2014年 InvestGu. All rights reserved.
//

#import "WHC_ButtonGroupView.h"
#define kLineWidth (1.0)
#define KANMATION_TIME 0.2
@implementation WHC_ButtonGroupParam
//返回默认样式
+(WHC_ButtonGroupParam *)getDefaultParamWithTitleArr:(NSArray*)titleArr{
    WHC_ButtonGroupParam * groupParam = [WHC_ButtonGroupParam new];
    groupParam.normalBackColor      = [UIColor grayColor];
    groupParam.selectedBackColor    = [UIColor blackColor];
    groupParam.markColor            = [UIColor clearColor];
    groupParam.segmentLineY         = 0.0;
    groupParam.segmentLineColor     = [UIColor blackColor];
    groupParam.normalTextColor      = [UIColor whiteColor];
    groupParam.selectedTextColor    = [UIColor grayColor];
    groupParam.titles               = titleArr;
    groupParam.images               = nil;
    groupParam.scroll               = NO;
    groupParam.headLine             = YES;
    groupParam.footLine             = YES;
    groupParam.firstSegmentLine     = YES;
    groupParam.markViewDown         = NO;
    groupParam.fontSize             = 16.0;
    groupParam.markPading           = 5.0;
    return groupParam;
}

@end

@interface WHC_ButtonGroupView ()<UIScrollViewDelegate>{
    NSMutableArray    * btns;                     //存储按钮数组
    NSMutableArray    * segmentLineLabs;          //存储分隔线数组
    WHC_ButtonGroupParam  * btnParam;             //存储创建参数
    UIScrollView      * sl;                       //滑动控件
    UIView            * markView;                 //游标控件
    UILabel           * headLine;                 //头部线
    UILabel           * footLine;                 //底部线

    NSInteger           currBtnIndex;             //当前按钮下标
    CGRect              rect;                     //备份该控件矩形区域
    CGPoint             center;                   //中心点

    CGFloat             screenWidth;              //屏幕宽度
    CGFloat             screenHeight;             //屏幕高度
}

@end

@implementation WHC_ButtonGroupView

//初始化控件
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        screenWidth = [UIScreen mainScreen].bounds.size.width;
        screenHeight = [UIScreen mainScreen].bounds.size.height;
        rect = frame;
        btns = [NSMutableArray array];
        segmentLineLabs = [NSMutableArray array];
        CGFloat    btnHeight = btnParam.btnHeight == 0.0 ? frame.size.height:btnParam.btnHeight;
        btnParam.btnHeight   = btnHeight;
        btnParam.btnWidth  = btnParam.btnWidth  == 0.0 ? (rect.size.width > screenWidth ? screenWidth : rect.size.width)/(CGFloat)btnParam.titles.count : btnParam.btnWidth;
        sl = [[UIScrollView alloc]initWithFrame:CGRectMake(0.0, 0.0,btnParam.scroll == NO ? frame.size.width : btnParam.scrollWidth, btnParam.btnHeight)];
        sl.backgroundColor = btnParam.normalBackColor;
        sl.delegate = self;
        sl.contentSize = CGSizeMake(btnParam.btnWidth * btnParam.titles.count, 0);
        sl.scrollEnabled = btnParam.scroll;
        sl.showsVerticalScrollIndicator = NO;
        sl.showsHorizontalScrollIndicator = NO;
        [self layoutUI];
        [self addSubview:sl];
        if(headLine != nil){
            [self bringSubviewToFront:headLine];
        }
        if(footLine != nil){
            [self bringSubviewToFront:footLine];
        }
    }
    return self;
}
//初始化控件
- (id)initWithFrame:(CGRect)frame withParam:(WHC_ButtonGroupParam*)param
{
    btnParam = param;
    return [self initWithFrame:frame];
}

//布局ui
-(void)layoutUI{
    NSInteger  count = btnParam.titles.count;
    CGFloat    btnWidth  = btnParam.btnWidth  == 0.0 ? (rect.size.width > screenWidth ? screenWidth : rect.size.width)/(CGFloat)count : btnParam.btnWidth;
    CGFloat    btnHeight = btnParam.btnHeight == 0.0 ? rect.size.height:btnParam.btnHeight;
    CGFloat    lineWidth = btnParam.headLine || btnParam.footLine ? kLineWidth : 0;
    btnParam.btnWidth    = btnWidth;
    btnParam.btnHeight   = btnHeight;
    for (NSInteger i = 0; i < count; i++) {
        UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.frame = CGRectMake(i * btnParam.btnWidth, 0.0, (btnParam.btnWidth - kLineWidth) + (i == count -1 ? kLineWidth : 0.0), btnParam.btnHeight);
        btn.tag = i;
        btn.titleLabel.font = [UIFont boldSystemFontOfSize:btnParam.fontSize];
        btn.backgroundColor = btnParam.normalBackColor;
        [btn setTitle:btnParam.titles[i] forState:UIControlStateNormal];
        if(btnParam.images.count > 0){
            [btn setImage:[UIImage imageNamed:btnParam.images[i]] forState:UIControlStateNormal];
            NSString * strText = @"冠军";
            //兼容低版本
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
            CGSize  fontSize = [strText sizeWithFont:[UIFont systemFontOfSize:btnParam.fontSize]];
#pragma clang diagnostic pop
            CGFloat  left = (btnParam.btnWidth -  fontSize.width * 2.0)/2.0;
            CGFloat  top  = 5.0;
            CGFloat  bottom = 5.0;
            CGFloat  right = left + fontSize.width;
            btn.imageEdgeInsets = UIEdgeInsetsMake(top, left, bottom, right);
        }
        [btn setTitleColor:btnParam.normalTextColor forState:UIControlStateNormal];
        [btn setTitleColor:btnParam.selectedTextColor forState:UIControlStateSelected];
        [btn addTarget:self action:@selector(clickBtns:) forControlEvents:UIControlEventTouchUpInside];
        if(i == btnParam.currIndex){
            btn.selected = YES;
            if(btnParam.selectedBackColor != nil)
                btn.backgroundColor = btnParam.selectedBackColor;
        }
        [sl addSubview:btn];
        [btns addObject:btn];
        if(!btnParam.firstSegmentLine && i >= count - 1){
            break;
        }
        UILabel  * segmentLine = [[UILabel alloc]initWithFrame:CGRectMake((btnParam.btnWidth - kLineWidth) * (i + 1) + i * kLineWidth, btnParam.segmentLineY, kLineWidth, btnHeight - 2 * btnParam.segmentLineY)];
        segmentLine.backgroundColor = btnParam.segmentLineColor;
        [segmentLineLabs addObject:segmentLine];
        [sl addSubview:segmentLine];
    }
    if(btnParam.firstSegmentLine){
        UILabel  * segmentLine = [[UILabel alloc]initWithFrame:CGRectMake(0.0, btnParam.segmentLineY, kLineWidth, btnHeight - 2 * btnParam.segmentLineY)];
        segmentLine.backgroundColor = btnParam.segmentLineColor;
        [segmentLineLabs addObject:segmentLine];
        [sl addSubview:segmentLine];
    }
    if(btnParam.headLine){
        headLine = [[UILabel alloc]initWithFrame:CGRectMake(0.0, 0.0, rect.size.width, lineWidth)];
        headLine.backgroundColor = btnParam.segmentLineColor;
        [self addSubview:headLine];
    }
    if(btnParam.footLine){
        footLine = [[UILabel alloc]initWithFrame:CGRectMake(0.0, btnParam.btnHeight - lineWidth, rect.size.width, lineWidth)];
        footLine.backgroundColor = btnParam.segmentLineColor;
        [self addSubview:footLine];
    }

    CGFloat markWidth = btnParam.btnWidth - 2 * btnParam.markPading;
    if (btnParam.markViewDown) {
        markView  = [[UIView alloc]initWithFrame:CGRectMake(btnParam.markPading, btnParam.btnHeight - 2.5, markWidth, 2.5)];
    }else{
        markView  = [[UIView alloc]initWithFrame:CGRectMake(btnParam.markPading, 1.0, markWidth, 2.5)];
    }
    markView.backgroundColor = btnParam.markColor;
    [sl addSubview:markView];

}

//单击按钮处理
-(void)clickBtns:(UIButton *)btn
{
    NSInteger  tag = btn.tag;
    [self changeSelectedStateButtonWithIndex:tag];
    if(_delegate){
        if([_delegate respondsToSelector:@selector(whcButtonGroup:index:)]){
            [_delegate whcButtonGroup:self index:tag];
        }
    }
}
//屏幕切换处理
-(void)switchUIOrientationWithIsHori:(BOOL)isHori withPading:(CGFloat)pad
{
    if (isHori){
        CGRect  rc = CGRectZero;
        rc = CGRectMake(0.0, 0.0, screenHeight, btnParam.btnHeight);
        self.frame = rc;
        self.center = CGPointMake(screenWidth - (pad + btnParam.btnHeight / 2.0) + pad + btnParam.btnHeight, screenHeight / 2.0);
        center = self.center;
        rc = CGRectMake(0.0, 0.0,btnParam.scroll == NO ? screenHeight : btnParam.scrollWidth, btnParam.btnHeight);
        sl.frame = rc;

        NSInteger btnCount = btns.count;
        CGFloat btnWidth = screenHeight / (CGFloat)btnCount;
        for (int i = 0; i < btnCount; i++) {
            UIButton * tempBtn = btns[i];
            rc = CGRectMake(i * btnWidth, 0.0, (btnWidth - kLineWidth) + (i == btnCount -1 ? kLineWidth : 0.0), btnParam.btnHeight);
            tempBtn.frame = rc;
        }

        NSInteger labCount = segmentLineLabs.count;
        for (int i = 0; i < labCount; i++) {
            UILabel * tempLab = segmentLineLabs[i];
            rc = CGRectMake((btnWidth - kLineWidth) * (i + 1) + i * kLineWidth, btnParam.segmentLineY, kLineWidth, btnParam.btnHeight - 2 * btnParam.segmentLineY);
            tempLab.frame = rc;
        }
        UILabel * tempLab = segmentLineLabs.lastObject;
        tempLab.frame = CGRectMake(0.0, btnParam.segmentLineY, kLineWidth, btnParam.btnHeight - 2 * btnParam.segmentLineY);

        if(headLine != nil){
            rc = CGRectMake(0.0, 0.0, screenHeight, kLineWidth);
            headLine.frame = rc;
        }
        if(footLine != nil){
            rc = CGRectMake(0.0, btnParam.btnHeight - kLineWidth, screenHeight, kLineWidth);
            footLine.frame = rc;
        }
        CGFloat markWidth = btnParam.btnWidth - 2 * btnParam.markPading;
        if(btnParam.markViewDown){
            rc = CGRectMake(btnParam.currIndex * btnWidth +  (btnWidth - markWidth)/2.0, btnParam.btnHeight - 2.5, markWidth, 2.5);
            markView.frame = rc;
        }else{
            rc = CGRectMake(btnParam.currIndex * btnWidth + (btnWidth - markWidth)/2.0, 1.0, markWidth, 2.5);
            markView.frame = rc;
        }

        self.transform = CGAffineTransformMakeRotation(M_PI_2);
        [UIView animateWithDuration:KANMATION_TIME animations:^{
            self.center = CGPointMake(center.x - (pad + btnParam.btnHeight), center.y);
        }];
    }else{
#if 0
        self.transform = CGAffineTransformMakeRotation(0);
        [UIView animateWithDuration:KANMATION_TIME animations:^{
//            self.center = center;
        }];
        CGRect  rc = CGRectZero;
        rc = rect;
        self.frame = rc;
        rc = CGRectMake(0.0, 0.0,btnParam.scroll == NO ? rect.size.width : btnParam.scrollWidth, btnParam.btnHeight);
        sl.frame = rc;
        NSInteger btnCount = btns.count;
        for (int i = 0; i < btnCount; i++) {
            UIButton * tempBtn = btns[i];
            rc = CGRectMake(i * btnParam.btnWidth, 0.0, (btnParam.btnWidth - kLineWidth) + (i == btnCount -1 ? kLineWidth : 0.0), btnParam.btnHeight);
            tempBtn.frame = rc;
        }
        NSInteger labCount = segmentLineLabs.count;
        for (int i = 0; i < labCount; i++) {
            UILabel * tempLab = segmentLineLabs[i];
            rc = CGRectMake((btnParam.btnWidth - kLineWidth) * (i + 1) + i * kLineWidth, btnParam.segmentLineY, kLineWidth, btnParam.btnHeight - 2 * btnParam.segmentLineY);
            tempLab.frame = rc;
        }
        if(headLine != nil){
            rc = CGRectMake(0.0, 0.0, rect.size.width, kLineWidth);
            headLine.frame = rc;
        }
        if(footLine != nil){
            rc = CGRectMake(0.0, btnParam.btnHeight - kLineWidth, rect.size.width, kLineWidth);
            footLine.frame = rc;
        }

        if(btnParam.markViewDown){
            rc = CGRectMake(btnParam.currIndex * btnParam.btnWidth +  (btnParam.btnWidth - btnParam.markWidth)/2.0, btnParam.btnHeight - 2.5, btnParam.markWidth, 2.5);
            markView.frame = rc;
        }else{
            rc = CGRectMake(btnParam.currIndex * btnParam.btnWidth + (btnParam.btnWidth - btnParam.markWidth)/2.0, 1.0, btnParam.markWidth, 2.5);
            markView.frame = rc;
        }
#endif
        self.center = CGPointMake(self.center.x + (pad + btnParam.btnHeight) * 2.0, self.center.y);
    }
}
//响应其他按钮
-(void)gotoOtherBtnOptionWithIndex:(NSInteger)index
{
    [self clickBtns:btns[index]];
}

//修改按钮标题
-(void)modifyButtonTitleForIndex:(NSInteger)index withTitle:(NSString*)title{
    UIButton * btn = btns[index];
    [btn setTitle:title forState:UIControlStateNormal];
}

//调整布局
-(void)adjustLayoutWithIndex:(NSInteger)index withTitle:(NSString*)title{
    //清空旧存储
    for(UIView * view in sl.subviews){
        [view removeFromSuperview];
    }
    NSMutableArray * arr = [NSMutableArray arrayWithArray:btnParam.titles];
    [arr removeLastObject];
    [arr addObject:((UIButton*)[btns lastObject]).titleLabel.text];
    if(title != nil){
        [arr insertObject:title atIndex:index];

    }else{
        [arr removeObjectAtIndex:index];
    }
    btnParam.titles = nil;
    btnParam.titles = [NSArray arrayWithArray:arr];
    btnParam.btnWidth = 0.0;
    btnParam.btnHeight = 0.0;
    btnParam.markPading = 0.0;
    [btns removeAllObjects];
    [segmentLineLabs removeAllObjects];
    markView = nil;
    headLine = nil;
    footLine = nil;
    [self layoutUI];
}
//添加按钮
-(BOOL)addButtonWithIndex:(NSInteger)index withTitle:(NSString*)title{
    BOOL result = NO;
    if(![btnParam.titles containsObject:title]){
        [self adjustLayoutWithIndex:index withTitle:title];
        result = YES;
    }
    return result;
}
//删除按钮
-(BOOL)deleteButtonWithIndex:(NSInteger)index withTitle:(NSString*)title{
    BOOL result = NO;
    if([btnParam.titles containsObject:title]){
        [self adjustLayoutWithIndex:index withTitle:nil];
        result = YES;
    }
    return result;
}

//改变按钮选中状态
-(void)changeSelectedStateButtonWithIndex:(NSInteger)index{
    currBtnIndex = index;
    for (UIButton * tempBtn in btns) {
        tempBtn.selected = NO;
        tempBtn.backgroundColor = btnParam.normalBackColor;
    }
    ((UIButton*)btns[index]).selected = YES;
    ((UIButton*)btns[index]).backgroundColor = btnParam.selectedBackColor;
    CGRect markRect = markView.frame;
    markRect.origin.x = ((UIButton*)btns[index]).frame.origin.x +
    (((UIButton*)btns[index]).frame.size.width - markRect.size.width) / 2.0;
    if(index == 0){
        index = 1;
    }else if (index == btnParam.titles.count - 1){
        index = btnParam.titles.count - 2;
    }
    [UIView animateWithDuration:0.1 animations:^{
        markView.frame = markRect;
        if(sl.scrollEnabled){
            if((index - 1) * btnParam.btnWidth > (sl.contentSize.width - sl.frame.size.width))return ;
            [sl setContentOffset:CGPointMake((index - 1) * btnParam.btnWidth, 0) animated:NO];
        }
    }];
}

@end

运行效果如图
WHC_ButtonGroupViewDemo下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值