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;
}
原文地址:https://www.cnblogs.com/zhongriqianqian/p/4159241.html