Select Items Programmatically in Uicollectionview

How to select item in collectionview programmatically?

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.

Select items programmatically in UICollectionView

I think you are missing this method from the UICollectionView Class Reference:

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

You can use this method multiple times if you want multiple selections.

Selecting UICollectionViewCell programmatically

Call them on mainThread they will work

DispatchQueue.main.async {
let indexPath = IndexPath(item: i, section: 0)
self.collectionView.selectItem(at: indexPath, animated: false, scrollPosition: .top)
self.collectionView(self.collectionView, didSelectItemAt: indexPath)
}

How can I programmatically select UICollection view cells and update a pointer array?

The code I posted before was just to show you a little bit about the logic of having a variable that tells you if the song is playing or not. But it is not a good production code, it was mostly for illustration purposes (it is not easy to maintain a dictionary and a pointer array). So, I'm gonna try to guide you in a different way so that your app becomes simpler to read later and you detach the function of playing as much as possible from your controller -> Reason: Imagine that later you would like to reuse the same cell to populate a collection view that displays the songs that correspond to an Album for example. Then you will have to refactor all the code to make your new collection view work as well. However, the point of any object oriented programming is that you can actually build "Objects" that can be reused as you may need.

So, first think what exactly your "song" object will have to be. Most probably is not only gonna be a path to a file that gets played anytime a user taps a cell from your collection view. I guess a song will also have an image, length, name, album, etc etc. If you continue creating arrays for each single variable that a song will need to display, you will probably end up with countless arrays that need to be maintained separately. That is not so easy and is surely more prone to fails.

The first thing the will be to create a class or an struct that actually contains all the data of you song. For example (using struct - you can use class if you want):

struct Song {

var songName : String
var isPlaying : Bool = false

init(songName : String) {
self.songName = songName
}
}

I'm only using two variables for the song object but you can add as many as you want. Just pay attention to which variable can be initialized when you create an instance of your "Song" object. In the example only the song name can be initialized, the Bool for playing is initialized by default to false and is the variable that tells you if the song is playing or not.

Then you can setup you Cell, which in this case will be the responsible for setting all the views depending on your "Song". For this you can create a custom class for the cell, in this case I just called it Cell, you can call it whatever you want.

class Cell : UICollectionViewCell {

var song : Song?

weak var cellDelegate : CellDelegate?

override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func setupViews() {
self.backgroundColor = .red
}

func play() {
if !(song?.isPlaying)! {
song?.isPlaying = true
print("Playing", (song?.songName)!)
return
}
song?.isPlaying = false
print("Stop", (song?.songName)!)
}

}

Notice that cell has play() function and a variable called song var song : Song?. The reason is that I am going to let each cell decide when to play or pause. This detaches the cell from the play function that you would use in collection view.

Now that you have a "Song" object you can easily create an array of songs in your view controller or any other class. For example:

var songArray : [Song] = [Song.init(songName: "Song One"), Song.init(songName: "Song Two"), Song.init(songName: "Song Three")]

Finally you can initialize each of the cells of the collection view with each of the songs in your song array. For that you will use the cellForItemAt function:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Cell
cell.song = songArray[indexPath.item]
cell.cellDelegate = self
return cell
}

Now, you will see that the cell also has a weak var called var cellDelegate : CellDelegate this is the protocol that you will use to control the cell play and pause function. You can read further about delegates later and how they help to detach your cell from the controller as much as possible. Also, another collection view controller may conform to this delegate and you will have the same access to the function of the cell without having to rewrite all the code.

The protocol can be set outside of your cell class:

protocol CellDelegate : class {
func didSelectCell (for cell: Cell)
}

Finally, conform the view controller to CellDelegate:

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource, CellDelegate

And now the code for playing, pausing, previous, next, etc etc becomes way simpler and cleaner

 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
currentIndexPathItem = indexPath.item
let cellToPlay = collectionView.cellForItem(at: IndexPath(item: currentIndexPathItem, section: 0)) as! Cell
didSelectCell(for: cellToPlay)
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
let cellToStop = collectionView.cellForItem(at: indexPath) as! Cell
if (cellToStop.song?.isPlaying)! { didSelectCell(for: cellToStop) }
}

@objc func previous () {
let playingCell = collectionView.cellForItem(at: IndexPath(item: currentIndexPathItem, section: 0)) as! Cell
if (playingCell.song?.isPlaying)! { didSelectCell(for: playingCell) }
if currentIndexPathItem - 1 < 0 { return }
else { currentIndexPathItem = currentIndexPathItem - 1 }
let cellToPlay = collectionView.cellForItem(at: IndexPath(item: currentIndexPathItem, section: 0)) as! Cell
didSelectCell(for: cellToPlay)
}

func didSelectCell(for cell: Cell) {
cell.play()
}

Notice the didSelectCell function, that is all you need to add to conform to the delegate and play or pause your song. And that is it. Much cleaner and much simpler to code.

How to preselect and highlight a cell from a UICollectionView

For what you are trying to do, use isSelected property of UICollectionViewCell.

On how isSelected works, refer to: https://medium.com/@p.gpt10/uicollectionviewcell-selection-made-easy-41dae148379d

For initially selecting a UICollectionViewCell use,

self.contentCollectionView.selectItem(at: IndexPath(row: 0, section: 0), animated: true, scrollPosition: .left)

Also, in didSelectItemAt method, you don't need to change isSelected or call above method. Just refer to the above tutorial and you will get everything you need.

Edit:

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
@IBOutlet weak var aCollectionView: UICollectionView!

override func viewDidLoad()
{
super.viewDidLoad()
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 10
}

func numberOfSections(in collectionView: UICollectionView) -> Int
{
collectionView.allowsMultipleSelection = true
return 1
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "aCell", for: indexPath as IndexPath) as! myCollectionViewCell
cell.myLabel.text = "ok"
cell.isSelected = false
cell.layer.borderColor = UIColor.black.cgColor
cell.layer.borderWidth = 2
if indexPath.row == 5
{
collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .left) //Add this line
cell.isSelected = true
}
return cell
}

override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
}

class myCollectionViewCell: UICollectionViewCell
{
@IBOutlet weak var myLabel: UILabel!

override var isSelected: Bool{
didSet{
if self.isSelected
{
super.isSelected = true
self.contentView.backgroundColor = UIColor(red:0.08, green:0.28, blue:0.45, alpha:1)
}
else
{
super.isSelected = false
self.contentView.backgroundColor = UIColor(red:0.13, green:0.37, blue:0.58, alpha:0.7)
}
}
}
}


Related Topics



Leave a reply



Submit