Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Previously selected UICollectionViewCells are deselected after non-selectable cell is tapped

I am implementing a UICollectionView with multiple selection enabled.

Some of my cells are selectable, some are not. Here is the chain of events:

  1. I select a few cells by tapping on them and returning YES to
    • shouldHighlightItemAtIndexPath:
    • shouldSelectItemAtIndexPath:
  2. I try to select a non-selectable cell by tapping on it (the non-selectionable aspect is achieved by returning NO to shouldSelectItemAtIndexPath:)
  3. Result: All selected cells are deselected and didDeselectItemAtIndexPath: is called on them. NOTE: shouldDeselectItemAtIndexPath: is not called.

Expected Result: Nothing happens.

Is this normal behavior? I can't find anything in the docs. If so, how can I go about not deselecting my cells?

like image 910
Fabien Warniez Avatar asked Feb 04 '14 23:02

Fabien Warniez


2 Answers

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeue...

    cell.userInteractionEnabled = isSelectableIndexPath(indexPath)

    return cell
}

func isSelectableIndexPath(indexPath: NSIndexPath) -> Bool {
    //logic to check if cell is selectable
}

This works by disabling interaction with the cell.

like image 70
noobular Avatar answered Sep 27 '22 23:09

noobular


I had to face exactly the same problem, with collectionView:shouldDeselectItemAtIndexPath: not being called. My solution consist of manually reselect the currently selected cell if I'm tapping on a non-selectable one:

- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    BOOL isSelectable = /* decide if currently tapped cell should be selectable */;

    NSIndexPath *selectedItemIndexPath = /* NSIndexPath of the current selected cell in the collection view, set in collectionView:didSelectItemAtIndexPath: */;

    if (!isSelectable) {
        // the cell isn't selectable, we have to reselect the previously selected cell that has lost selection in the meanwhile
        // without reloading first the cell the selection is not working...
        [collectionView reloadItemsAtIndexPaths:@[selectedItemIndexPath]];
        [collectionView selectItemAtIndexPath:selectedItemIndexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone];
    }

    return isSelectable;
}

If your collection view is scrolling (hiding the currently selected cell) remember to reselect the cell in collectionView:cellForItemAtIndexPath:.

I don't like too much this solution, it's too "hacky", but it works. I would expect to do all the logic in the collectionView:shouldDeselectItemAtIndexPath: but it isn't called and I don't understand why.

like image 26
chare Avatar answered Sep 27 '22 23:09

chare