iOS的自定义的滑动菜单控件

ZJQBOSwipeMenuOption.h

//
//  ZJQBOSwipeMenuOption.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface ZJQBOSwipeMenuOption : NSObject

@property (nonatomic,assign) CGRect frame;//菜单区视图的frame属性

@property (nonatomic,strong) UIColor* selectedTextColor;//菜单被选中时的文字颜色
@property (nonatomic,strong) UIColor* unselectedTextColor;//菜单未选中时的文字颜色
@property (nonatomic,strong) UIColor* selectedTextBackground;//菜单被选中时的文字背景颜色
@property (nonatomic,strong) UIColor* unselectedTextBackground;//菜单未选中时的文字背景颜色
@property (nonatomic,strong) UIFont* textFont;//菜单字体大小

@property (nonatomic,strong) UIImage* selectedLineImage;//菜单被选中时底线颜色图片
@property (nonatomic,strong) UIImage* unselectedLineImage;//菜单未选中时底线颜色图片
@property (nonatomic,assign) CGFloat lineImageHeight;//菜单底线图片的高度

@property (nonatomic,assign) NSInteger max;//菜单数量显示上限,超过max数量的菜单必须通过左右滑动手势显示


#pragma mark 对象初始化-对象方法
-(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max;

#pragma mark 对象初始化-类方法
+(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max;
@end

ZJQBOSwipeMenuOption.m

//
//  ZJQBOSwipeMenuOption.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ZJQBOSwipeMenuOption.h"

@implementation ZJQBOSwipeMenuOption



#pragma mark 对象初始化-对象方法
-(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max
{
    if (self=[super init]) {
        _frame=frame;
        _selectedTextColor=selectedTextColor;
        _unselectedTextColor=unselectedTextColor;
        _selectedTextBackground=selectedTextBackground;
        _unselectedTextBackground=unselectedTextBackground;
        _textFont=textFont;
        _selectedLineImage=selectedLineImage;
        _unselectedLineImage=unselectedLineImage;
        _lineImageHeight=lineImageHeight;
        _max=max;
    }
    return self;
}

#pragma mark 对象初始化-类方法
+(instancetype)initWithFrame : (CGRect) frame
    andWithSelectedTextColor : (UIColor*) selectedTextColor
  andWithUnselectedTextColor : (UIColor*) unselectedTextColor
andWithSelectedTextBackground : (UIColor*) selectedTextBackground
andWithUnselectedTextBackground : (UIColor*) unselectedTextBackground
             andWithTextFont : (UIFont*) textFont
    andWithSelectedLineImage : (UIImage*) selectedLineImage
  andWithUnselectedLineImage : (UIImage*) unselectedLineImage
      andWithLineImageHeight : (CGFloat) lineImageHeight
                  andWithMax : (NSInteger) max
{
    ZJQBOSwipeMenuOption* option = [[ZJQBOSwipeMenuOption alloc] initWithFrame:frame
                                                      andWithSelectedTextColor:selectedTextColor
                                                    andWithUnselectedTextColor:unselectedTextColor
                                                 andWithSelectedTextBackground:selectedTextBackground
                                               andWithUnselectedTextBackground:unselectedTextBackground
                                                               andWithTextFont:textFont
                                                      andWithSelectedLineImage:selectedLineImage
                                                    andWithUnselectedLineImage:unselectedLineImage
                                                        andWithLineImageHeight:lineImageHeight
                                                                    andWithMax:max];
    return option;
}
@end

ZJQBOSwipeMenuOption.h

//
//  ZJQSwipeMenuView.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ZJQBOSwipeMenuOption.h"

@protocol ZJQSwipeMenuViewDelegate <NSObject>

-(void)menuClickedAtIndex : (NSInteger) index;

@end

@interface ZJQSwipeMenuView : UIView

@property (nonatomic,strong) NSMutableArray* menus; //菜单数组:字符串数组类型,例如[@"菜单1",@"菜单2",...]
@property (nonatomic,strong) ZJQBOSwipeMenuOption* option;//菜单参数
@property (nonatomic,strong) id <ZJQSwipeMenuViewDelegate> delegate;//委托代理

-(instancetype)initWithMenus : (NSMutableArray*) menus
               andWithOption : (ZJQBOSwipeMenuOption*) option;
@end

ZJQSwipeMenuView.m

//
//  ZJQSwipeMenuView.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ZJQSwipeMenuView.h"
#define TAG_MENU 10000 //菜单默认起始tag属性值
#define TAG_LINE 20000 //菜单下划线默认起始tag属性值

@implementation ZJQSwipeMenuView
{
@private
    CGFloat menuWidth_;//单个菜单占用的宽度
    NSInteger count_;//总的菜单个数
    NSInteger showedCount_;//屏幕显示的菜单个数
    NSInteger rightIndexInAllMenus_;//最右边菜单索引号,在整个菜单数组中从0开始计数的
    BOOL hasUnshowedMenu_;//是否有屏幕未展示的菜单,如果菜单总数超过菜单上限,那么肯定为YES
    NSInteger selectedMenuIndex_;//当前选择的菜单索引号
    
    CGPoint touchBeginPoint_;//触摸移动开始位置
    CGFloat minX_;//菜单区起点x最小值
    CGFloat maxX_;//菜单区起点x最大值
}

#pragma mark --------> 构造器 <--------
-(instancetype)initWithMenus : (NSMutableArray*) menus
              andWithOption : (ZJQBOSwipeMenuOption*) option
{
    if (self=[super init]) {
        _menus=menus;
        _option=option;
        [self _init];
    }
    return self;
}

#pragma mark --------> 初始化 <--------
-(void)_init {
    [self _initView];
    [self _initVariables];
    [self _initMenus];
}

-(void)_initView{
    self.frame=_option.frame;//菜单区frame
}

-(void)_initVariables{
    count_=_menus.count;//总的菜单个数
    showedCount_=(count_>_option.max)?_option.max:count_;//屏幕显示的菜单个数,如果超过菜单显示上限,则后面的不显示
    CGFloat width = self.frame.size.width;//菜单区的宽度
    CGFloat frameX=self.frame.origin.x;
    menuWidth_=width/showedCount_;//单个菜单占用的宽度
    rightIndexInAllMenus_=showedCount_-1;//最右边菜单索引号
    selectedMenuIndex_=0;//屏幕上被选中菜单的索引号
    hasUnshowedMenu_=(count_>_option.max)?YES:NO;//是否有屏幕未展示的菜单
    
    //重新计算菜单区的宽度
    CGFloat newWidth = count_*menuWidth_;
    newWidth = (newWidth>width)? newWidth:width;
    CGRect newFrame = self.frame;
    newFrame.size.width=newWidth;
    self.frame=newFrame;
    //计算菜单区起点x坐标的范围
    maxX_=frameX;
    minX_=maxX_+width-self.frame.size.width;
}

-(void)_initMenus {
    for (int i=0; i<count_; i++) {
        //
        BOOL isSelected = (selectedMenuIndex_==i);
        [self _addMenu:isSelected andWithIndexInShowedMenus:i andWithIndexInAllMenus:i andIsAppnedAtTail:YES];
    }
}

#pragma mark --------> tag与菜单项的关系操作区 <--------
-(NSInteger) _getMenuTagWithIndexInAllMenus : (NSInteger) indexInAllMenus{
    return TAG_MENU+indexInAllMenus;
}

-(NSInteger) _getIndexInAllMenusWithMenuTag : (NSInteger) menuTag{
    return menuTag-TAG_MENU;
}

-(NSInteger) _getLineTagWithIndexInAllMenus : (NSInteger) indexInAllMenus{
    return TAG_LINE+indexInAllMenus;
}

-(NSInteger) _getIndexInAllMenusWithLineTag : (NSInteger) lineTag{
    return lineTag-TAG_LINE;
}


#pragma mark --------> 添加1项菜单 <--------
-(void)_addMenu : (BOOL) isSelected andWithIndexInShowedMenus : (NSInteger) indexInShowedMenus andWithIndexInAllMenus :(NSInteger) indexInAllMenus andIsAppnedAtTail : (BOOL) isAppendAtTail{
    //菜单文字
    NSString* menuTitle = _menus[indexInAllMenus];
    
    UILabel* lblTabMenu = [[UILabel alloc]init];
    lblTabMenu.frame = CGRectMake(indexInShowedMenus*menuWidth_, 0, menuWidth_, self.frame.size.height-_option.lineImageHeight);
    lblTabMenu.backgroundColor=(isSelected)?_option.selectedTextBackground:_option.unselectedTextBackground;
    lblTabMenu.text=menuTitle;
    lblTabMenu.textColor=(isSelected)?_option.selectedTextColor:_option.unselectedTextColor;
    lblTabMenu.font=_option.textFont;
    lblTabMenu.textAlignment=NSTextAlignmentCenter;
    lblTabMenu.tag=[self _getMenuTagWithIndexInAllMenus:indexInAllMenus];
    
    lblTabMenu.userInteractionEnabled=YES;
    UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(_menuClicked:)];
    [lblTabMenu addGestureRecognizer:tapGestureRecognizer];
    
    
    
    UIImageView* ivLine = [[UIImageView alloc]init];
    ivLine.image = (isSelected)?_option.selectedLineImage:_option.unselectedLineImage;
    ivLine.frame= CGRectMake(indexInShowedMenus*menuWidth_, self.frame.size.height-_option.lineImageHeight, menuWidth_, _option.lineImageHeight);
    ivLine.tag=[self _getLineTagWithIndexInAllMenus:indexInAllMenus];

    if (isAppendAtTail) {
        [self addSubview:lblTabMenu];
        [self addSubview:ivLine];
    }else{
        //注意插入最前面的时候,顺序要和上面的相反
        [self insertSubview:ivLine atIndex:0];
        [self insertSubview:lblTabMenu atIndex:0];
    }
    ivLine.alpha=0;
    [UIView animateWithDuration:0.5 animations:^{ ivLine.alpha = 1; } completion:^(BOOL finished){ }];
    
}


#pragma mark --------> 按钮点击和滑动手势事件区 <--------
-(void) _menuClicked : (UITapGestureRecognizer*) sender {
    UILabel* lblMenu = (UILabel*)sender.view;
    NSInteger tag = lblMenu.tag;
    NSInteger menuIndex = [self _getIndexInAllMenusWithMenuTag:tag];
    
    [self _didSelectMenuAtIndex:menuIndex];
    
    //让delegate去继续执行
    if (_delegate) {
        if ([_delegate respondsToSelector:@selector(menuClickedAtIndex:)]) {
            [_delegate menuClickedAtIndex:menuIndex];
        }
    }
}

-(void) _didSelectMenuAtIndex : (NSInteger) menuIndex {
    
    //将之前选择的菜单取消选择
    NSInteger lblOldMenuTag = [self _getMenuTagWithIndexInAllMenus:selectedMenuIndex_];
    UILabel* lblOldMenu = (UILabel*) [self viewWithTag:lblOldMenuTag];
    lblOldMenu.backgroundColor=_option.unselectedTextBackground;
    lblOldMenu.textColor=_option.unselectedTextColor;
    
    NSInteger oldLineTag = [self _getLineTagWithIndexInAllMenus:selectedMenuIndex_];
    UIImageView* ivOldLine = (UIImageView*) [self viewWithTag:oldLineTag];
    ivOldLine.image=_option.unselectedLineImage;
    
    
    //选择当前点中的菜单
    NSInteger lblMenuTag = [self _getMenuTagWithIndexInAllMenus:menuIndex];
    UILabel* lblMenu = (UILabel*) [self viewWithTag:lblMenuTag];
    lblMenu.backgroundColor=_option.selectedTextBackground;
    lblMenu.textColor=_option.selectedTextColor;
    
    NSInteger lineTag = [self _getLineTagWithIndexInAllMenus:menuIndex];
    UIImageView* ivLine = (UIImageView*) [self viewWithTag:lineTag];
    ivLine.image=_option.selectedLineImage;

    
    //更新当前选中的菜单索引
    selectedMenuIndex_=menuIndex;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = [touches anyObject];
    touchBeginPoint_=[touch locationInView:self];
    [super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = [touches anyObject];
    CGPoint point = [touch locationInView:self];
    //x坐标变化
    CGFloat xChanged = point.x-touchBeginPoint_.x;
    //xChanged<0表示向左移动,xChanged>0表示向右移动
    //判断是否可以移动菜单
    BOOL isCanMoveMenu = NO;
    CGFloat newX = self.frame.origin.x+xChanged;
    isCanMoveMenu = (newX>=minX_ && newX<=maxX_);
    //修改菜单区frame
    CGRect newFrame = self.frame;
    if (isCanMoveMenu) {
        newFrame.origin.x=newFrame.origin.x+xChanged;
    }else{
        if (xChanged>0) {
            newFrame.origin.x=maxX_;
        }else{
            newFrame.origin.x=minX_;
        }
    }
    self.frame=newFrame;
}

@end

 调用方法:

ViewController996.h

//
//  ViewController996.h
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "ZJQBOSwipeMenuOption.h"
#import "ZJQSwipeMenuView.h"

@interface ViewController996 : UIViewController<ZJQSwipeMenuViewDelegate>


@property (nonatomic,strong) ZJQSwipeMenuView* swipeMenuView;
@property (nonatomic,strong) ZJQBOSwipeMenuOption* menuOption;
@end

ViewController996.m

//
//  ViewController996.m
//  demo010
//
//  Created by zhoujianqiang on 15/9/26.
//  Copyright © 2015年 zhoujianqiang. All rights reserved.
//

#import "ViewController996.h"
#define IOS7 [[[UIDevice currentDevice]systemVersion] floatValue] >= 7.0 //判断SDK版本号是否是7.0或7。0以上


@interface ViewController996 ()

@end

@implementation ViewController996

#pragma mark ----------> 系统方法区 <----------
- (void)viewDidLoad {
    [super viewDidLoad];
    [self _init];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}


#pragma mark ----------> 初始化 <----------
-(void)_init{
    if (IOS7) {
        self.edgesForExtendedLayout=UIRectEdgeNone;
    }
    self.title=@"Swipe Menu";
    [self _initPropertys];
}

-(void)_initPropertys{
    CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, 40);
    _menuOption = [ZJQBOSwipeMenuOption initWithFrame:frame andWithSelectedTextColor:[UIColor redColor] andWithUnselectedTextColor:[UIColor blackColor] andWithSelectedTextBackground:[UIColor whiteColor] andWithUnselectedTextBackground:[UIColor whiteColor] andWithTextFont:[UIFont systemFontOfSize:13] andWithSelectedLineImage:[UIImage imageNamed:@"r"] andWithUnselectedLineImage:[UIImage imageNamed:@"w"] andWithLineImageHeight:3 andWithMax:6];
    
    NSMutableArray* menus = [[NSMutableArray alloc]init];
    for (int i=0; i<10; i++) {
        [menus addObject:[NSString stringWithFormat:@"菜单%d",i]];
    }
    
    _swipeMenuView = [[ZJQSwipeMenuView alloc]initWithMenus:menus andWithOption:_menuOption];
    [self.view addSubview:_swipeMenuView];
    
    _swipeMenuView.delegate=self;
}

#pragma mark ----------> 实现ZJQSwipeMenuViewDelegate中的方法 <----------
-(void)menuClickedAtIndex:(NSInteger)index{
    NSLog(@"menuClickedAtIndex:index=%ld,%@",index,_swipeMenuView.menus[index]);
}

@end

效果图:



 

 完整工程代码为附件中的demo010.zip

猜你喜欢

转载自stephen830.iteye.com/blog/2247238