How to select item in collectionview programmatically?

I have a UICollectionView. The UICollectionView's datasource is a NSArray of students (from CoreData). I want the current student item be selected/highlighted.

How can I do this? I know there is a method:

- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath 
                     animated:(BOOL)animated 
               scrollPosition:(UICollectionViewScrollPosition)scrollPosition;

which takes as arguments an NSIndexPath and UICollectionViewScrollPosition.

I have the datasource (NSArray of students populated from CoreData) and the student object to be selected.

So, how do I get the NSIndexPath and UICollectionViewScrollPosition? Or is there any other way to highlight an item?

Answers


You can simply use this after [self.collectionView reloadData]

[self.collectionView 
   selectItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0] 
                animated:YES
          scrollPosition:UICollectionViewScrollPositionCenteredVertically];

where index is the index number for the selected student.


Swift

let indexPath = self.collectionView.indexPathsForSelectedItems?.last ?? IndexPath(item: 0, section: 0)
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: UICollectionView.ScrollPosition.centeredHorizontally)

From your question I'm assuming you only ever have one selected student, I did a similar thing with a collection of icons the user could select. Firstly in view did load I did:

override func viewDidLoad() {
    super.viewDidLoad()

    iconCollectionView.delegate = self
    iconCollectionView.dataSource = self
    iconCollectionView.allowsMultipleSelection = false
    iconCollectionView.selectItemAtIndexPath(NSIndexPath(forItem: 0, inSection: 0), animated: false, scrollPosition: .None)
}

Here I default to selecting the first cell, you would use StudentArray.indexOf to get your selected student index. Then to show the which item is selected I did:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = iconCollectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! IconCollectionViewCell
    cell.imageView.image = UIImage(named: imageResourceNames.pngImageNames[indexPath.row])
    if cell.selected {
        cell.backgroundColor = UIColor.grayColor()
    }
    return cell
}

This is called when the collection is first displayed, then to react to changes in selection:

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.cellForItemAtIndexPath(indexPath)?.backgroundColor = UIColor.grayColor()
}

func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
    collectionView.cellForItemAtIndexPath(indexPath)?.backgroundColor = UIColor.clearColor()
}

Obviously there are many ways to show cell selection, my way is simple but that's all I needed to do.

EDIT: Since posting the above I have realised it's simpler to just add an observer to selected in the cell class:

class IconCollectionViewCell: UICollectionViewCell {

...

    override var selected: Bool {
        didSet {
            backgroundColor = selected ? UIColor.grayColor() : UIColor.clearColor()
        }
    }
}

With this in place the there is no need to handle didSelect or didDeselect or check for selected in cellForItemAtIndexPath, the cell does it automatically.


let indexPathForFirstRow = IndexPath(row: 0, section: 0)
    paymentHeaderCollectionView.selectItem(at: indexPathForFirstRow, animated: false, scrollPosition: UICollectionViewScrollPosition.left)
    self.collectionView(paymentHeaderCollectionView, didSelectItemAt: indexPathForFirstRow)

Need Your Help

Factory Pattern with Open Generics

c# generics dependency-injection asp.net-core

In ASP.NET Core, one of the things you can do with Microsoft's dependency injection framework is bind "open generics" (generic types unbound to a concrete type) like so:

How to convert an existing assembly to a ms unit test assembly?

c# .net unit-testing visual-studio-2010 built-in

In Visual Studio 2010 Pro, how can I easily convert a classic assembly to a ms unit test assembly ?