Search code examples
iosobjective-cuicollectionviewuicollectionviewcelluicollectionviewdelegate

Change Background of UICollectionView Cell on Tap


I have a UICollectionView that I have created programmatically. I would like for the collection view to behave in the following way:

1. User touches cell
2. Cell background color changes
3. User releases touch
4. Cell background color changes

This should be a quick color change that happens just before the selector related to the tap action is executed in which the viewcontroller containing the collection view is popped off the stack.

I have been looking at this question: UICollectionView cell change background while tap

in which there is the following summary of methods to use for this purpose:

// Methods for notification of selection/deselection and highlight/unhighlight events.
// The sequence of calls leading to selection from a user touch is:
//
// (when the touch begins)
// 1. -collectionView:shouldHighlightItemAtIndexPath:
// 2. -collectionView:didHighlightItemAtIndexPath:
//
// (when the touch lifts)
// 3. -collectionView:shouldSelectItemAtIndexPath: or -    collectionView:shouldDeselectItemAtIndexPath:
// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:
// 5. -collectionView:didUnhighlightItemAtIndexPath:

I am assuming I only need to implement one of the above methods from 'when touch begins' and 'when touch ends.' But no matter what I do, it appears that a background color changes and then remains changed. Here is an example of something I attempted which did not work:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
 {
   //pop vc 
 }

- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor redColor];
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

This results in the cell background color being changed only to red. I also looked at this question: UICollectionView Select and Deselect issue and tried implementing [UICollectionView selectItemAtIndexPath:animated:scrollPosition:] and calling it inside of didSelectItemAtIndexPath, but this did not work either. Collection view data source and delegate are set.


Solution

  • The problem is that you are changing the color on highlight and changing it back on deselect instead that on unhighlight

    You should simply change this:

    - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
    {
      UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
      cell.contentView.backgroundColor = [UIColor greenColor];
    }
    

    to this:

    - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
    {
      UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
      cell.contentView.backgroundColor = [UIColor greenColor];
    }
    

    Also, if you don't want to wait a bit before getting your highlight happen you should set the delaysContentTouches property of the collection view to NO

    Edit: also ensure that you call

    [collectionView deselectItemAtIndexPath:indexPath animated:NO];
    

    inside the -didSelectItemAtIndexPath method