你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS開發系列之常用自定義控件開發集—自定義UITableViewCell側滑菜單控件開發

iOS開發系列之常用自定義控件開發集—自定義UITableViewCell側滑菜單控件開發

編輯:IOS開發綜合

在很多app中就有UITableViewCell左滑出現菜單如系統刪除按鈕,但是系統的只能有一個,有很多需求需要個性化不僅可以放文字還可以放按鈕修改背景色創建多個菜單項,那麼系統提供的肯定不適合,所以我們需要自己手工打造。
直接上代碼如下:
WHC_MenuCell.h 頭文件如下:

//
//  WHC_MenuCell.m
//  WHC_MenuCell
//
//  Created by 吳海超 on 15/4/3.
//  Copyright (c) 2015年 Sinosun Technology Co., Ltd. All rights reserved.
//

#import 
@class WHC_MenuCell;
@protocol WHC_MenuCellDelegate 

- (BOOL)WHC_MenuCell:(WHC_MenuCell*)whcCell didPullCell:(NSInteger)index;            //拉動tableView的回調

@end

@interface WHC_MenuCell : UITableViewCell
@property (nonatomic,assign)   CGFloat                 menuViewWidth;                //菜單總寬度
@property (nonatomic,retain)   NSArray               * menuItemTitles;               //每個菜單的標題
@property (nonatomic,retain)   NSArray               * menuItemTitleColors;          //每個菜單的文字顏色
@property (nonatomic,retain)   NSArray               * menuItemBackImages;           //每個菜單的背景圖片
@property (nonatomic,retain)   NSArray               * menuItemNormalImages;         //每個菜單正常的圖片
@property (nonatomic,retain)   NSArray               * menuItemSelectedImages;       //每個菜單選中的圖片
@property (nonatomic,retain)   NSArray               * menuItemBackColors;           //每個菜單的背景顏色
@property (nonatomic,retain)   NSArray               * menuItemWidths;               //每個菜單的寬度
@property (nonatomic,strong)   UIView                * ContentView;                  //自定義內容view
@property (nonatomic,assign)   CGFloat                 fontSize;                     //字體大小
@property (nonatomic,assign)   NSInteger               index;                        //cell下標
@property (nonatomic,assign)   iddelegate;                     //cell代理

//單擊菜單項
- (void)clickMenuItem:(UIButton*)sender;

//關閉菜單
- (BOOL)closeCellWithAnimation:(BOOL)b;

//關閉批量菜單
- (BOOL)closeCellWithTableView:(UITableView*)tableView index:(NSInteger)index animation:(BOOL)b;

//開始或者正在拉開菜單
- (void)startScrollviewCell:(BOOL)state x:(CGFloat)moveX;

//結束拉開菜單
- (void)didEndScrollViewCell:(BOOL)state;

@end

WHC_MenuCell.m源文件如下:

//
//  WHC_MenuCell.m
//  WHC_MenuCell
//
//  Created by 吳海超 on 15/4/3.
//  Copyright (c) 2015年 Sinosun Technology Co., Ltd. All rights reserved.
//

#import "WHC_MenuCell.h"
#define KWHC_MENUCELL_ANMATION_PADING (10.0)
@interface WHC_MenuCell (){
    BOOL                                  _isOpen;              //是否打開菜單
    BOOL                                  _isScorllClose;       //是否滾動關閉菜單
    CGFloat                               _startX;              //存儲拉開菜單開始觸摸x坐標
    UIView                              * _menuView;            //菜單view
    UIPanGestureRecognizer              * _panGesture;          //手勢
}

@end

@implementation WHC_MenuCell

//初始化UI
- (void)initUI{
    _panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];
    _panGesture.delegate = self;
    [self.contentView addGestureRecognizer:_panGesture];

    UITapGestureRecognizer  * tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTapGestrue:)];
    tapGesture.delegate = self;
    [self.contentView addGestureRecognizer:tapGesture];

    if(_menuItemTitles == nil){
        _menuItemTitles = @[];
    }
    if(_menuItemBackImages == nil){
        _menuItemBackImages = @[];
    }
    if(_menuItemBackColors == nil){
        _menuItemBackColors = @[[UIColor redColor]];
    }
    if(_menuItemTitleColors == nil){
        _menuItemTitleColors = @[[UIColor blackColor]];
    }
    if(_menuItemWidths == nil){
        _menuItemWidths = @[];
    }
    if(_menuItemNormalImages == nil){
        _menuItemNormalImages = @[];
    }
    if(_menuItemSelectedImages == nil){
        _menuItemSelectedImages = @[];
    }

    CGFloat  _menuViewX = CGRectGetWidth(_ContentView.frame) - _menuViewWidth;
    _menuView = [[UIView alloc]initWithFrame:CGRectMake(_menuViewX + CGRectGetMinX(_ContentView.frame), 0.0, _menuViewWidth, CGRectGetHeight(_ContentView.frame))];
    _menuView.backgroundColor = [UIColor clearColor];
    [self.contentView insertSubview:_menuView belowSubview:_ContentView];

    NSInteger menuItemCount = _menuItemTitles.count;
    NSInteger menuBackImageCount = _menuItemBackImages.count;
    NSInteger menuBackColorCount = _menuItemBackColors.count;
    NSInteger menuTitleColorCount = _menuItemTitleColors.count;
    NSInteger menuItemWidthCount = _menuItemWidths.count;
    NSInteger menuItemNormalImageCount = _menuItemNormalImages.count;
    NSInteger menuItemSelectedImageCount = _menuItemSelectedImages.count;
    CGFloat btnWidth = _menuViewWidth / (CGFloat)menuItemCount;

    CGFloat (^currentWidth)(NSInteger i) = ^(NSInteger i){
        CGFloat  width = 0.0;
        for (NSInteger j = 0; j <= i ; j++) {
            width += [_menuItemWidths[j] floatValue];
        }
        return width;
    };

    //創建菜單按鈕
    for (NSInteger i = 0; i < menuItemCount; i++) {
        UIButton  * btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.tag = i;
        CGRect btnRc = CGRectMake(i * btnWidth, 0.0, btnWidth, CGRectGetHeight(_ContentView.frame));
        btn.frame = btnRc;
        if(menuItemWidthCount == menuItemCount){

            btnRc.origin.x = currentWidth(i - 1);
            btnRc.size.width = [_menuItemWidths[i] floatValue];
            btn.frame = btnRc;
        }
        [btn setTitle:_menuItemTitles[i] forState:UIControlStateNormal];
        NSInteger  titleColorIndex = i;
        if(titleColorIndex >= menuTitleColorCount){
            titleColorIndex = menuTitleColorCount - 1;
            if(titleColorIndex < 0){
                titleColorIndex = 0;
            }
        }
        if(titleColorIndex < menuTitleColorCount){
            [btn setTitleColor:_menuItemTitleColors[titleColorIndex] forState:UIControlStateNormal];
        }
        NSInteger  imageIndex = i;
        if(imageIndex >= menuBackImageCount){
            imageIndex = menuBackImageCount - 1;
            if(imageIndex < 0){
                imageIndex = 0;
            }
        }
        if(imageIndex > menuBackImageCount){
            [btn setBackgroundImage:[UIImage imageNamed:_menuItemBackImages[imageIndex]] forState:UIControlStateNormal];
        }

        NSInteger  colorIndex = i;
        if(colorIndex >= menuBackColorCount){
            colorIndex = menuBackColorCount - 1;
            if(colorIndex < 0){
                colorIndex = 0;
            }
        }
        if(colorIndex < menuBackColorCount){
            btn.backgroundColor = _menuItemBackColors[colorIndex];
        }

        if(i < menuItemNormalImageCount){
            NSString  * imageName = _menuItemNormalImages[i];
            if(imageName != nil && imageName.length){
                [btn setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
            }

            if(i < menuItemSelectedImageCount){
                NSString  * selectedImageName = _menuItemSelectedImages[i];
                if(selectedImageName != nil && selectedImageName.length){
                    [btn setImage:[UIImage imageNamed:selectedImageName] forState:UIControlStateHighlighted];
                }
            }
        }
        btn.titleLabel.minimumScaleFactor = 0.1;
        btn.titleLabel.adjustsFontSizeToFitWidth = YES;
        if(_fontSize == 0.0){
            _fontSize = 18.0;
        }
        btn.titleLabel.font = [UIFont boldSystemFontOfSize:_fontSize];
        [btn addTarget:self action:@selector(clickMenuItem:) forControlEvents:UIControlEventTouchUpInside];
        [_menuView addSubview:btn];
    }

}


//加載xib
- (void)awakeFromNib{
    [self initUI];
}

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if(self){
    }
    return self;
}

//設置滾動列表時菜單關閉狀態
- (void)setIsScrollClose{
    _isScorllClose = NO;
}

//下面兩個方法有子類實現屬於觸摸監聽方法
- (void)startScrollviewCell:(BOOL)state x:(CGFloat)moveX{}
- (void)didEndScrollViewCell:(BOOL)state{}

//單擊菜單項
- (void)clickMenuItem:(UIButton *)sender{
    [self closeCellWithAnimation:YES];
}

//批量關閉tableview上得多個cell菜單
- (BOOL)closeCellWithTableView:(UITableView*)tableView index:(NSInteger)index animation:(BOOL)b{

    NSArray  * indexPathArr = [tableView indexPathsForVisibleRows];
    BOOL  handleResult = NO;
    for (NSIndexPath * indexPath in indexPathArr) {
        if(_index != indexPath.row && index > -1){

            WHC_MenuCell * cell = (WHC_MenuCell *)[tableView cellForRowAtIndexPath:indexPath];
            [cell setIsScrollClose];
            if([cell closeCellWithAnimation:b]){
                handleResult = YES;
            }
        }else if(index <= -1){

            WHC_MenuCell * cell = (WHC_MenuCell *)[tableView cellForRowAtIndexPath:indexPath];
            if(_index != indexPath.row){
                [cell setIsScrollClose];
            }
            if([cell closeCellWithAnimation:b]){
                handleResult = YES;
            }
        }
    }
    return handleResult;
}

//關閉cell菜單
- (BOOL)closeCellWithAnimation:(BOOL)b{
    BOOL isClose = NO;
    if(_isOpen){
        isClose = YES;
        if(b){
            [UIView animateWithDuration:0.2 animations:^{
                _ContentView.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
            }completion:^(BOOL finished) {
                _isOpen = NO;
                [self didEndScrollViewCell:_isOpen];
            }];
        }else{
            _ContentView.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
            _isOpen = NO;
            [self didEndScrollViewCell:_isOpen];
        }
    }
    return isClose;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];
    // Configure the view for the selected state
}

//手勢處理
- (void)handlePanGesture:(UIPanGestureRecognizer*)panGesure{

    switch (panGesure.state) {
        case UIGestureRecognizerStateBegan:{

            _startX = _ContentView.transform.tx;
            _isScorllClose = [_delegate WHC_MenuCell:self didPullCell:_index];
        }
            break;
        case UIGestureRecognizerStateChanged:{
            if(_isScorllClose && _isOpen == NO){
                return;
            }
            CGFloat    currentX = _ContentView.transform.tx;
            CGFloat    moveDistanceX = [panGesure translationInView:panGesure.view].x;
            CGFloat    velocityX = [panGesure velocityInView:panGesure.view].x;
            CGFloat    moveX = _startX + moveDistanceX;

            if(velocityX > 0){//right
                if(currentX >= KWHC_MENUCELL_ANMATION_PADING){
                    [panGesure setTranslation:CGPointMake(KWHC_MENUCELL_ANMATION_PADING, 0.0) inView:panGesure.view];
                    break;
                }
            }else{
                if(currentX < -_menuViewWidth){
                    moveX = currentX - 0.4;
                    [panGesure setTranslation:CGPointMake(moveX, 0.0) inView:panGesure.view];
                }
            }
            _ContentView.transform = CGAffineTransformMakeTranslation(moveX, 0.0);
            [self startScrollviewCell:_isOpen x:moveDistanceX];
        }
            break;
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateEnded:{
            _isScorllClose = NO;
            if(_ContentView.transform.tx > 0.0){

                [UIView animateWithDuration:0.2 animations:^{
                    _ContentView.transform = CGAffineTransformMakeTranslation(-KWHC_MENUCELL_ANMATION_PADING, 0.0);
                }completion:^(BOOL finished) {
                    _isOpen = NO;
                    [self didEndScrollViewCell:_isOpen];
                    [UIView animateWithDuration:0.2 animations:^{
                        _ContentView.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
                    }];
                }];

            }else if (_ContentView.transform.tx < 0){

                CGFloat  tx  = fabsf(_ContentView.transform.tx);
                if(tx < _menuViewWidth / 2.0 || (tx < _menuViewWidth && _isOpen)){
                    [UIView animateWithDuration:0.2 animations:^{
                        _ContentView.transform = CGAffineTransformMakeTranslation(0.0, 0.0);
                    }completion:^(BOOL finished) {
                        _isOpen = NO;
                        [self didEndScrollViewCell:_isOpen];
                    }];
                }else{
                    [UIView animateWithDuration:0.2 animations:^{
                        _ContentView.transform = CGAffineTransformMakeTranslation(-_menuViewWidth, 0.0);
                    }completion:^(BOOL finished) {
                        _isOpen = YES;
                        [self didEndScrollViewCell:_isOpen];
                    }];
                }
            }
        }
            break;
        default:
            break;
    }
}

- (void)handleTapGestrue:(UITapGestureRecognizer*)tapGesture{

}

#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{

    if([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){

        return [_delegate WHC_MenuCell:self didPullCell:-1];

    }else if([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class] ]){

        UIPanGestureRecognizer  * panGesture = (UIPanGestureRecognizer*)gestureRecognizer;
        CGPoint                   velocityPoint = [panGesture velocityInView:panGesture.view];
        if(fabsf(velocityPoint.x) > fabsf(velocityPoint.y)){
            return YES;
        }else{
            _isScorllClose = [_delegate WHC_MenuCell:self didPullCell:-1];
            return _isScorllClose;
        }
    }
    return NO;
}
@end

運行效果如圖

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved