UICollectionView 在单元格上拖动手指以选择它们

Posted

技术标签:

【中文标题】UICollectionView 在单元格上拖动手指以选择它们【英文标题】:UICollectionView drag finger over cells to select them 【发布时间】:2014-12-09 23:20:55 【问题描述】:

使用UICollectionView,是否可以通过在其中几个单元格上拖动手指来选择多个单元格?例如,如果您将手指拖动到一行 6 上,然后向下移动到下一行,它将选择所有这些。

尝试了一些简单的东西:

UISwipeGestureRecognizer *swipeGuesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)];
[self.collectionView addGestureRecognizer:swipeGuesture];

但这似乎只调用了第一个被触摸的单元格上的方法。

有什么想法吗?

【问题讨论】:

您是否尝试过使用 UIPanGestureRecognizer?并根据平移事件的位置,跟踪通过了哪些单元格。当手势结束时,您将拥有一组选定的单元格。 @MikeWelsh 解决方案是一个选项,您也可以尝试覆盖 UICollectionView 类并覆盖触摸功能,例如:- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event @MikeWelsh 太棒了!那行得通!您可以将其添加为答案吗? @MikeWelsh - 该解决方案的问题在于它阻止了整个 UICollectionView 的滚动。 @NicHubbard 您可以检查初始平移是否水平,如果不是,则忽略它。您必须配置识别器和委托,但这当然是可行的。 【参考方案1】:

Swift 3:滑动以选择自动滚动和工作滚动。

var selectMode = false
var lastSelectedCell = IndexPath()

func setupCollectionView() 
    collectionView.canCancelContentTouches = false
    collectionView.allowsMultipleSelection = true
    let longpressGesture = UILongPressGestureRecognizer(target: self, action: #selector(didLongpress))
    longpressGesture.minimumPressDuration = 0.15
    longpressGesture.delaysTouchesBegan = true
    longpressGesture.delegate = self
    collectionView.addGestureRecognizer(longpressGesture)

    let panGesture = UIPanGestureRecognizer(target: self, action: #selector(didPan(toSelectCells:)))
    panGesture.delegate = self
    collectionView.addGestureRecognizer(panGesture)


func selectCell(_ indexPath: IndexPath, selected: Bool) 
    if let cell = collectionView.cellForItem(at: indexPath) 
        if cell.isSelected 
            collectionView.deselectItem(at: indexPath, animated: true)
            collectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredVertically, animated: true)
         else 
            collectionView.selectItem(at: indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.centeredVertically)
        
        if let numberOfSelections = collectionView.indexPathsForSelectedItems?.count 
            title = "\(numberOfSelections) items selected"
        
    


func didPan(toSelectCells panGesture: UIPanGestureRecognizer) 
    if !selectMode 
        collectionView?.isScrollEnabled = true
        return
     else 
        if panGesture.state == .began 
            collectionView?.isUserInteractionEnabled = false
            collectionView?.isScrollEnabled = false
        
        else if panGesture.state == .changed 
            let location: CGPoint = panGesture.location(in: collectionView)
            if let indexPath: IndexPath = collectionView?.indexPathForItem(at: location) 
                if indexPath != lastSelectedCell 
                    self.selectCell(indexPath, selected: true)
                    lastSelectedCell = indexPath
                
            
         else if panGesture.state == .ended 
            collectionView?.isScrollEnabled = true
            collectionView?.isUserInteractionEnabled = true
            swipeSelect = false
        
    


func didLongpress() 
    swipeSelect = true

【讨论】:

这个效果很好,我必须改变的一件事是选择panGesture.state == .ended状态的单元格以实现流畅的动画 提供的示例并非在所有情况下都有效。一方面,您需要实现gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:。此外,您需要先检查平移方向(水平或垂直)。如果它主要不是水平的,则回退到滚动。【参考方案2】:

您可以使用 UIPanGestureRecognizer。并根据平移事件的位置,跟踪通过了哪些单元格。当手势结束时,您将拥有一组选定的单元格。

确保将cancelsTouchesInView 设置为NO。您需要使用 gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:gestureRecognizerShouldBegin 设置委托,以确保 CollectionView 仍然可以滚动

【讨论】:

【参考方案3】:

ios 13 及更高版本中,您可以简单地使用内置的多选手势。见Selecting Multiple Items with a Two-Finger Pan Gesture。确保将collectionView.allowsMultipleSelectionDuringEditing 设置为true

【讨论】:

那是两个手指的东西,是完全不同的概念 太棒了!这正是我所需要的。

以上是关于UICollectionView 在单元格上拖动手指以选择它们的主要内容,如果未能解决你的问题,请参考以下文章

如何在 UICollectionView 中检测“仅单指”单元格上的双击?

在滚动期间点击时,UICollectionView 不再识别单元格上的点击?

在单元格上设置角半径会破坏 UICollectionView 的性能

UICollectionView 标头仅在第一个单元格上调用一次

完成加载后,在 UICollectionView 中的第一个单元格上调用函数

如何使用 UICollectionView 的 selectItem 在 collectionView 单元格上绘图?