自定义cell侧滑删除(仿别人的app)

将近一年半没有写blog了,最近项目排期不是很紧,整理一下以前遇到的问题,之前我们的项目要上一个消息中心,设计师看到京东的消息中心的cell侧滑删除比较好,就要求我们实现跟京东一模一样的侧滑删除,这对于一年半之前我这样的菜鸟来说,是一件比较头疼的事情。不多说,现在整理一下,先看思路。
  • 第一步我们要对cell进行处理,创建一个scrollView上去,以便可以滑动
  • 其次放两个View分别显示内容和显示取消和删除两个按钮,这里我使用代理方法实现监控按钮的点击事件
  • 解决cell原生和scrollView的手势冲突
  • 注意一点:当有cell处于编辑状态时,tableView是不可以滑动的,这里跟原生的侧滑删除类似
现在看一下Demo代码,这为了节省时间 cell我就用Xib拖了 Demo地址
  • cell的.m文件
 #import <UIKit/UIKit.h>
@protocol JDMessageCellDelegate;
@interface JDMessageCell : UITableViewCell
@property (nonatomic, assign) id<JDMessageCellDelegate> delegate;
//使用数据初始化cell 这里不一定是dictionary 也有可能是model
-(void)configCellWith:(NSDictionary *)dict;
// 判断是否有cell处于编辑模式下
-(void)enableEditAction:(BOOL)canEdit;
//退出编辑模式
-(void)quitEditMode;
@end
  • 看一下需要实现的代理方法
@protocol JDMessageCellDelegate <NSObject>
//cell 开始编辑模式
-(void)cellBeginEditMode:(JDMessageCell *)cell;
// cell 结束编辑模式
-(void)cellEndEditMode:(JDMessageCell *)cell;
//删除这条记录
-(void)deleteMessageInCell:(JDMessageCell *)cell;
@end
  • 在.m文件中对声明的方法和相对应的属性进行设置
#import "JDMessageCell.h"
@interface JDMessageCell ()<UIScrollViewDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *bgScrollView;
@property (weak, nonatomic) IBOutlet UIButton *cancelBtn;
@property (weak, nonatomic) IBOutlet UIButton *deleteBtn;
@property (weak, nonatomic) IBOutlet UIView *bgView;
@property (weak, nonatomic) IBOutlet UIView *leftView;
@property (weak, nonatomic) IBOutlet UILabel *leftTitleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *leftImgView;
@property (weak, nonatomic) IBOutlet UIView *rightView;
@property (weak, nonatomic) IBOutlet UILabel *cancelLabel;
@property (weak, nonatomic) IBOutlet UILabel *deleteLabel;
@end
@implementation JDMessageCell
-(void)awakeFromNib {
    [super awakeFromNib];
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    //这些属性都可以在Xib中设置 为了显示设置了什么属性写了出来
    _bgScrollView.userInteractionEnabled = NO;
    _bgScrollView.bounces = NO;
    _bgScrollView.pagingEnabled = YES;
    _bgScrollView.delegate = self;
    //解决cell原生侧滑删除冲突
    [self.contentView addGestureRecognizer:_bgScrollView.panGestureRecognizer];
    _bgScrollView.contentSize = CGSizeMake(_bgScrollView.frame.size.width * 2, _bgScrollView.frame.size.height);
    //给cell的rightView空白区域添加个手势
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(quitEditCell:)];
    tap.numberOfTapsRequired = 1;
    [self.rightView addGestureRecognizer:tap];
}
-(void)configCellWith:(NSDictionary *)dict {
    [_bgScrollView setContentOffset:CGPointZero animated:NO];
    _bgScrollView.userInteractionEnabled = NO;
}
-(void)enableEditAction:(BOOL)canEdit {
    if (canEdit) {
        [self.contentView addGestureRecognizer:_bgScrollView.panGestureRecognizer];
    }
    else {
        [self.contentView removeGestureRecognizer:_bgScrollView.panGestureRecognizer];
    }
}
//退出编辑模式
-(void)quitEditMode{
    [_bgScrollView setContentOffset:CGPointMake(0, 0) animated:YES];
    _bgScrollView.userInteractionEnabled = NO;
}
-(void)quitEditCell:(UITapGestureRecognizer *)gesture {
    [self quitEditMode];
    if (self.delegate && [self.delegate respondsToSelector:@selector(cellEndEditMode:)]) {
        [self.delegate cellEndEditMode:self];
    }
}
#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    CGFloat cellWidth = scrollView.frame.size.width;
    if (scrollView.contentOffset.x >= cellWidth / 2.0) {
        scrollView.userInteractionEnabled = YES;
        //此时cell处于编辑状态
        if (self.delegate && [self.delegate respondsToSelector:@selector(cellBeginEditMode:)]) {
            [self.delegate cellBeginEditMode:self];
        }
    }
    else {
        scrollView.userInteractionEnabled = NO;
        //cell 退出编辑状态
        if (self.delegate && [self.delegate respondsToSelector:@selector(cellEndEditMode:)]) {
            [self.delegate cellEndEditMode:self];
        }
    }
}
#pragma mark - Button Action
-(IBAction)cancelBtnAction:(id)sender {
    [self quitEditMode];
    if (self.delegate && [self.delegate respondsToSelector:@selector(cellEndEditMode:)]) {
        [self.delegate cellEndEditMode:self];
    }
}
-(IBAction)deleteBtnAction:(id)sender {
    if (self.delegate && [self.delegate respondsToSelector:@selector(deleteMessageInCell:)]) {
        [self.delegate deleteMessageInCell:self];
    }
}
到这里cell的实现算是完成了,下面就来看一下tableView的实现,为了节省时间我就不单独抽出来一个TableView了,直接在controller中开始写了O(∩_∩)O哈哈~
  • 我这里只是一个demo没有要公开出去的属性和方法,所以.h文件没有东西就不写了
  • 看一下.m文件吧 (我这里分组数和cell高度就写死来演示了)
#import "ViewController.h"
#import "JDMessageCell.h"
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource, JDMessageCellDelegate> {
    JDMessageCell *cellAtMode; //正在编辑的cell
}
@property (weak, nonatomic) IBOutlet UITableView *jdTableView;
@end
@implementation ViewController
-(void)viewDidLoad {
    [super viewDidLoad];
    //register cell
    [_jdTableView registerNib:[UINib nibWithNibName:@"JDMessageCell" bundle:nil] forCellReuseIdentifier:@"JDMessageCell"];
}
#pragma mark -UITableViewDataSource
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 4;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    JDMessageCell *jdCell = [tableView dequeueReusableCellWithIdentifier:@"JDMessageCell"];
//这个方法一定要使用,如果不使用请写一个公开的方法调用一下
    [jdCell configCellWith:[NSDictionary dictionary]];
    jdCell.delegate = self;
    return jdCell;
}
#pragma mark - UITableViewDelegate
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 201.0;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    //如果存在正在编辑的cell 点击其他的cell时,退出编辑
    if (cellAtMode) {
        [cellAtMode quitEditMode];
        [self enableTableViewEditAction:YES];
        cellAtMode = nil;
        NSLog(@"编辑退出");
    }
    else {
        NSLog(@"点击了%ld组", indexPath.section);
    }
}
//这里是判断tableView能不能滑动的,当有cell处在编辑模式不能滑动
-(void)enableTableViewEditAction:(BOOL)enable {
    self.jdTableView.scrollEnabled = enable;
    for (NSInteger index = 0; index < self.jdTableView.numberOfSections; index++) {
        JDMessageCell *salesCell = [self.jdTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index]];
        [salesCell enableEditAction:enable];
    }
}
#pragma mark - JDMessageCellDelegate
//实现cell的代理方法
-(void)cellBeginEditMode:(JDMessageCell *)cell {
    [self enableTableViewEditAction:NO];
    [cell enableEditAction:YES];
    cellAtMode = cell;
}
//结束编辑了
-(void)cellEndEditMode:(JDMessageCell *)cell {
    [self enableTableViewEditAction:YES];
    cellAtMode = nil;
}
-(void)deleteMessageInCell:(JDMessageCell *)cell {
    NSInteger index = [self.jdTableView indexPathForCell:cell].section;
    [self removeCellAtIndex:index];
}
#pragma mark - Helper Method
-(void)removeCellAtIndex:(NSInteger)index {
    NSLog(@"删除了第%ld组", index);
    //这里要看tableView是plain 还是grouped ->我这里使用的是分组形式的
}
-(void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end
写到这里基本上就结束了,UI方面知识做了简单的处理(比较难看 O(∩_∩)O哈哈~),相信结构出来了,根据项目具体UI渲染不难吧。对于.m中的实现这里就不在细说了,代码中有注释,以上的代码基本上满足了项目中的需求,下面上几张图看一下
  • cell 的.xib 文件层级结构图
Cell层级结构.jpeg
  • 运行截屏
有一个cell正在编辑截图.png
说明一下,本人程序菜鸟一枚,这个Demo仅仅是满足于项目的需求,相信京东的大神做的肯定比我的思路要简单,而且代码也比较优雅,如果谁有更好的解决方法,欢迎留言交流。O(∩_∩)O哈哈~
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容