将近一年半没有写blog了,最近项目排期不是很紧,整理一下以前遇到的问题,之前我们的项目要上一个消息中心,设计师看到京东的消息中心的cell侧滑删除比较好,就要求我们实现跟京东一模一样的侧滑删除,这对于一年半之前我这样的菜鸟来说,是一件比较头疼的事情。不多说,现在整理一下,先看思路。
- 第一步我们要对cell进行处理,创建一个scrollView上去,以便可以滑动
- 其次放两个View分别显示内容和显示取消和删除两个按钮,这里我使用代理方法实现监控按钮的点击事件
- 解决cell原生和scrollView的手势冲突
- 注意一点:当有cell处于编辑状态时,tableView是不可以滑动的,这里跟原生的侧滑删除类似
现在看一下Demo代码,这为了节省时间 cell我就用Xib拖了 Demo地址
#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
#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中的实现这里就不在细说了,代码中有注释,以上的代码基本上满足了项目中的需求,下面上几张图看一下
说明一下,本人程序菜鸟一枚,这个Demo仅仅是满足于项目的需求,相信京东的大神做的肯定比我的思路要简单,而且代码也比较优雅,如果谁有更好的解决方法,欢迎留言交流。O(∩_∩)O哈哈~