UITableViewCell左滑显示按钮菜单
http://blog.jobbole.com/67272/
编辑模式下左滑可以显示DELETE按钮。如何可以自定义左滑显示的按钮呢?
整体思路
1.自定义UITableViewCell,并为其contentView添加左滑时希望显示的按钮。
2.在contentView上添加一个相同大小subView,作为正常情况下tableViewCell显示的内容。
3.为此subView添加pan事件,滑动的时候移动其位置,使按钮可以显示出来。
需要注意的问题
具体实现(仿微信效果)
新建自定义的TableViewCell
1.新建自定义的TableViewCell:DogTableViewCell。在storyboard中关联并添加左滑时希望显示的按钮。
2.在contentView上添加一个相同大小subView:containerView,作为正常情况下tableViewCell显示的内容。
3.设置containerView相对于其父view(contentView)的约束,并为其左右约束连接IBOutlet。左右滑动的时候需要修改这两个约束的值。
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *contentViewRightConstraint; @property (nonatomic, weak) IBOutlet NSLayoutConstraint *contentViewLeftConstraint;
左滑显示按钮
1.在awakeFromNib时添加UIPanGestureRecognizer。
self.panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panThisCell:)]; self.panRecognizer.delegate = self; [self.containerView addGestureRecognizer:self.panRecognizer];
2.左滑动,移动containerView,显示按钮。
在UIGestureRecognizerStateBegan时,保存初始坐标:
self.panStartPoint = [recognizer translationInView:self.containerView]; self.startingRightLayoutConstraintConstant = self.contentViewRightConstraint.constant;
UIGestureRecognizerStateChanged时,根据新坐标判断是否左移。如果是的话,改变左右约束:
if (panningLeft){ CGFloat constant = MIN(-deltaX, [self buttonTotalWidth]); self.contentViewRightConstraint.constant = constant; self.contentViewLeftConstraint.constant = -self.contentViewRightConstraint.constant; //8 self.trackButton.hidden = NO; self.deleteButton.hidden = NO; }
在UIGestureRecognizerStateEnded时,根据移动的多少,判断要全部打开还是关闭,并用动画实现:
if (self.contentViewRightConstraint.constant >= halfOfButtonOne) { [self setConstraintsToShowAllButtons:YES notifyDelegateDidOpen:YES]; } else { [self resetConstraintContstantsToZero]; }
按钮显示时,点击任何位置隐藏按钮
1.增加UITapGestureRecognizer和UILongPressGestureRecognizer
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapThisCell)]; tap.delegate = self; [self.containerView addGestureRecognizer:tap]; UILongPressGestureRecognizer *ltap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(tapThisCell)]; ltap.delegate = self; ltap.minimumPressDuration = 0.01; ltap.enabled = YES; [self.containerView addGestureRecognizer:ltap];
2.在gestureRecognizerShouldBegin中进行判断:
如果tableView是编辑模式(已显示按钮),并且收到的事件是点击手势(UILongPressGestureRecognizer),则隐藏按钮,并退出编辑模式。
如果没有在编辑模式,并且收到的是滑动手势,则响应手势。
其他情况下不响应手势。
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ if (self.tableView.editState == YES && self.panRecognizer != gestureRecognizer){ [self.tableView disableEdit]; return YES; } if (self.panRecognizer == gestureRecognizer && self.tableView.editState == NO){ return YES; } if (self.panRecognizer == gestureRecognizer && self.tableView.editCell != self){ return NO; } return NO; }
tableView的上下滑动和tableViewCell的左滑动互斥
1.定义三种状态
#define ScrolStateNone 0//正常未滑动状态
#define ScrolStateDelete 1//左滑状态
#define ScrolStateScrol 2//上下滑动状态
2.UIGestureRecognizerStateChanged时,判断是上下滑还是左滑,并设置状态:
if (scrolState == ScrolStateNone){ if (abs(deltaX) < abs(deltaY)){ scrolState = ScrolStateScrol; return; } else{ scrolState = ScrolStateDelete; [self.tableView.tableView setScrollEnabled:NO]; } }
如果在上下滑动状态,则不再处理UIGestureRecognizerStateChanged
if (scrolState == ScrolStateScrol){ return; }
3.UIGestureRecognizerStateEnded时,如果为上下滑动状态,则还原为正常未滑动状态。
if (scrolState == ScrolStateScrol){ scrolState = ScrolStateNone; return; }
4.如果在滑动,则不响应其他手势。
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{ if (scrolState != ScrolStateNone) return NO; return YES; }