在“设置”等应用程序中,当您点击推动屏幕的单元格时,然后从屏幕左侧向后滑动,您可以看到所选单元格背景颜色褪色的取消选择,并且它是完全交互式的 - 如果您滑动一半,然后向后滑动所选背景视图将恢复完全不透明。
在我的应用程序中,我没有更改任何默认行为,当我从左侧滑动返回时,所选单元格背景颜色保持完全不透明,直到滑动手势完成,然后它快速淡出以取消选择它.
如何通过滑动返回手势实现交互式取消选择单元格?
要在 iOS 11 及更高版本中启用交互式取消选择,您可以使用
UITableViewController
,因为它为您实现了它,或者您可以通过在过渡协调器旁边设置取消选择动画来实现它,如下所示:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
if (selectedIndexPath) {
if (self.transitionCoordinator) {
[self.transitionCoordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) {
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
} completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
if (context.cancelled) {
[self.tableView selectRowAtIndexPath:selectedIndexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
}];
} else {
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:animated];
}
}
}
在 Swift 中:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let selectedIndexPath = tableView.indexPathForSelectedRow {
if let coordinator = transitionCoordinator {
coordinator.animate(alongsideTransition: { context in
self.tableView.deselectRow(at: selectedIndexPath, animated: true)
}) { context in
if context.isCancelled {
self.tableView.selectRow(at: selectedIndexPath, animated: false, scrollPosition: .none)
}
}
} else {
self.tableView.deselectRow(at: selectedIndexPath, animated: animated)
}
}
}
类似的实现适用于
UICollectionView
:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let indexPath = collectionView.indexPathsForSelectedItems?.first {
if let coordinator = transitionCoordinator {
coordinator.animate(alongsideTransition: { _ in
self.collectionView.deselectItem(at: indexPath, animated: true)
}, completion: { context in
if context.isCancelled {
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: [])
}
})
} else {
collectionView.deselectItem(at: indexPath, animated: animated)
}
}
}
看起来好像
clearsSelectionOnViewWillAppear
实际上可能是由 viewDidAppear:
而不是 viewWillAppear:
调用的,只有在转换完全结束后才会发生更改,如果取消交互式转换,则根本不会发生(如果是)在 viewWillAppear:
中,它会的)。这看起来像是一个 UIKit
bug,因为文档明确指出应该在 viewWillAppear:
中调用它
将以下代码行放入
viewWillAppear:
中,您将获得您正在寻找的确切行为,我刚刚尝试过。这可能正是属性触发的行为,只是方法错误。
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
使用私有 API(不安全 - Apple 将拒绝您的应用程序)
#import <objc/message.h>
#import <objc/runtime.h>
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
((void (*)(id, SEL, BOOL, id))objc_msgSend)(self.collectionView, sel_registerName("_deselectAllAnimated:notifyDelegate:"), YES, nil);
}