iOS 自定义TableView侧滑

2017-12-29  本文已影响94人  jemmy_xl

开发经常用到cell侧滑的功能,iOS8之前需要我们自定义,因为iOS8之前的侧滑,只能显示一个按钮。在iOS8之后苹果公司推出了新的API,UITableViewRowAction类,可以添加多个功能。

// 必须写的方法(否则iOS 8无法删除,iOS 9及其以上不写没问题),和editActionsForRowAtIndexPath配对使用,里面什么不写也行  
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {  
      
}  
  
// 添加自定义的侧滑功能  
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {  
    // 添加一个删除按钮  
      
    UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {  
        // 先移除数据源数据  
        [self.dataArray removeObjectAtIndex:indexPath.row];  
        // 再动态刷新UITableView  
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];  
        NSLog(@"删除按钮");  
    }];  
      
    UITableViewRowAction *topRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"置顶" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {  
        NSLog(@"置顶按钮");  
          
    }];  
    /// 设置按钮颜色,Normal默认是灰色的,Default默认是红色的  
    topRowAction.backgroundColor = [UIColor orangeColor];  
      
    UITableViewRowAction *cancelRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"取消关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {  
        NSLog(@"取消关注按钮");  
    }];  
      
    return @[deleteRowAction,topRowAction,cancelRowAction];  
}  

但是需求有时候就是想要侧滑带有图片的效果,苹果的UITableViewRowAction 是不带图片的。
先看效果图:


8442F82F-3466-433F-ADC1-1AACF098352C.png

我自定义的思路: 给cell添加滑动手势,根据手势来移动cell.contentView.frame来移动位置。在gestureRecognizerShouldBegin判断是否开启了侧滑,开始后,在cell的底部添加一个试图,用来放删除,等按钮的superview。这样就达到了侧滑的效果。

给每一个cell添加一个滑动的手势UIPanGestureRecognizer,

- (void)panAction:(UIPanGestureRecognizer *)panRecognizer {
    CGPoint point = [panRecognizer translationInView:panRecognizer.view];
    UIGestureRecognizerState state = panRecognizer.state;
    [panRecognizer setTranslation:CGPointZero inView:panRecognizer.view];
    
    if (state == UIGestureRecognizerStateChanged) {
        CGRect frame = self.contentView.frame;
        frame.origin.x += point.x;
        if (frame.origin.x > 15) {
            frame.origin.x = 15;
        } else if (frame.origin.x < -30 -(sideslipsBtnW*self.count)) {
            frame.origin.x = -30 -(sideslipsBtnW*self.count);
        }
        self.contentView.frame = frame;
        
    } else if (state == UIGestureRecognizerStateEnded) {
        CGPoint velocity = [panRecognizer velocityInView:panRecognizer.view];
        if (self.contentView.frame.origin.x == 0) {
            return;
        } else if (self.contentView.frame.origin.x > 5) {
            [self hiddenWithBounceAnimation];
        } else if (fabs(self.contentView.frame.origin.x) >= 40 && velocity.x <= 0) {
            [self showSideslip];
        } else {
            [self hiddenSideslip];
        }
        
    } else if (state == UIGestureRecognizerStateCancelled) {
        [self hiddenAllSideslip];
    }
    
}

在cell添加手势你会发现你的tableView滚动不了。因为与TableView手势冲突了,回YES即可同时执行多种手势

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    if ([otherGestureRecognizer.view isKindOfClass:[UITableView class]]) {
        return YES;
    }
    return NO;
}

在代理里面判断是否要触发侧滑,当cell滑动的角度大于45°,则不触发侧滑。如果侧滑出现后,你不要滑动TableView的话,将上面的gestureRecognizer注释。

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    
    if (gestureRecognizer == _panRecognizer) {
        if (!self.tableView.scrollEnabled) {
            [self hiddenAllSideslip];
            return NO;
        }
        
        UIPanGestureRecognizer *gesture = (UIPanGestureRecognizer *)gestureRecognizer;
        CGPoint translation = [gesture translationInView:gesture.view];
        
        // 如果手势相对于水平方向的角度大于45°, 则不触发侧滑
        BOOL shouldBegin = fabs(translation.y) <= fabs(translation.x);
        if (!shouldBegin) return NO;
        
        shouldBegin = YES;
        
        if (shouldBegin) {
            if (self.rightBtnImageArray.count == 0) return NO;
  //   添加侧滑试图。
            [self setActions:self.rightBtnImageArray];
        }
        return shouldBegin;
    }else if (gestureRecognizer == _tableViewPan) {
        if (self.tableView.scrollEnabled) {
            return NO;
        }
    }
    return YES;
}

通过self.tableView.visibleCells获取到cell列表关闭侧滑。

- (void)hiddenAllSideslip {
    for (NHReceiveTableViewCell *cell in self.tableView.visibleCells) {
        if ([cell isKindOfClass:NHReceiveTableViewCell.class]) {
            [cell hiddenSideslip];
        }
    }
}
上一篇下一篇

猜你喜欢

热点阅读