通过向后滑动手势以交互方式取消选择选定的单元格

问题描述 投票:0回答:3

在“设置”等应用程序中,当您点击推动屏幕的单元格时,然后从屏幕左侧向后滑动,您可以看到所选单元格背景颜色褪色的取消选择,并且它是完全交互式的 - 如果您滑动一半,然后向后滑动所选背景视图将恢复完全不透明。

在我的应用程序中,我没有更改任何默认行为,当我从左侧滑动返回时,所选单元格背景颜色保持完全不透明,直到滑动手势完成,然后它快速淡出以取消选择它.

如何通过滑动返回手势实现交互式取消选择单元格?

ios uitableview uicollectionview
3个回答
22
投票

要在 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)
        }
    }
}

13
投票

看起来好像

clearsSelectionOnViewWillAppear
实际上可能是由
viewDidAppear:
而不是
viewWillAppear:
调用的,只有在转换完全结束后才会发生更改,如果取消交互式转换,则根本不会发生(如果是)在
viewWillAppear:
中,它会的)。这看起来像是一个
UIKit
bug,因为文档明确指出应该在
viewWillAppear:

中调用它

将以下代码行放入

viewWillAppear:
中,您将获得您正在寻找的确切行为,我刚刚尝试过。这可能正是属性触发的行为,只是方法错误。

[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];

0
投票

使用私有 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);
}
© www.soinside.com 2019 - 2024. All rights reserved.