You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UIKit如何实现tableview cell侧滑返回时保持高亮并跟随手势取消高亮

实现方案

这个交互是UIKit内置支持的能力,无需自定义手势监听,只需要按以下规则配置即可:

原理说明

核心逻辑是延迟cell选中状态的取消时机,跟随导航控制器的pop交互转场进度动态处理:

  • 侧滑返回过程中保持cell高亮
  • 转场完成(完全返回列表页)时执行取消高亮动画
  • 转场取消(滑动到一半退回详情页)时保留cell选中状态

代码实现

1. 如果你使用系统UITableViewController

仅需设置一个属性即可获得默认效果:

// Swift
clearsSelectionOnViewWillAppear = true
// Objective-C
self.clearsSelectionOnViewWillAppear = YES;

这个属性默认就是开启状态,只要你没有手动关闭就会自带跟随侧滑取消高亮的效果。

2. 自定义UIViewController嵌套UITableView

需要自己在viewWillAppear中处理转场协调逻辑:

Swift 代码

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    guard let selectedIndexPath = tableView.indexPathForSelectedRow else { return }
    
    if let coordinator = transitionCoordinator {
        // 跟随转场动画执行取消选中逻辑
        coordinator.animate(alongsideTransition: { context in
            if !context.isCancelled {
                self.tableView.deselectRow(at: selectedIndexPath, animated: true)
            }
        }, completion: { context in
            // 转场取消时恢复选中状态
            if context.isCancelled {
                self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
            }
        })
    } else {
        // 非交互转场(比如点击返回按钮)直接取消选中
        tableView.deselectRow(at: selectedIndexPath, animated: animated)
    }
}

// 点击cell的回调里不要调用deselectRow,直接执行push逻辑即可
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let detailVC = DetailViewController()
    // 你的传参逻辑
    navigationController?.pushViewController(detailVC, animated: true)
}

Objective-C 代码

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    
    NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
    if (!selectedIndexPath) return;
    
    id<UIViewControllerTransitionCoordinator> coordinator = self.transitionCoordinator;
    if (coordinator) {
        [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            if (!context.isCancelled) {
                [self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
            }
        } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            if (context.isCancelled) {
                [self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
            }
        }];
    } else {
        [self.tableView deselectRowAtIndexPath:selectedIndexPath animated:animated];
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    DetailViewController *detailVC = [[DetailViewController alloc] init];
    // 你的传参逻辑
    [self.navigationController pushViewController:detailVC animated:YES];
}

注意事项

  • 不要在didSelectRowAt方法中直接调用deselectRow,否则cell会立刻取消高亮,无法跟随侧滑手势显示交互效果
  • 如果自定义了UINavigationController的delegate,确保没有拦截系统的转场协调逻辑,否则transitionCoordinator会返回空
  • 该实现逻辑同样适用于UICollectionView,仅需替换UITableView的选中/取消选中方法为UICollectionView对应的方法即可

内容的提问来源于stack exchange,提问作者qiuyang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 21:45:01