krishna ravichander
krishna ravichander

Reputation: 49

Auto Select Middle Visible Cell Of Collection View

I'm trying to select and highlight the middle cell of the visible cells in a collection view at any given time. The collection view in question displays days for six months forwards and back.

I've tried using the scroll view delegates and the collection view delegates. But all that works is select and highlight code in didSelectItem() collection view delegate.

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    print("delegate called")
    collectionView.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
    collectionView.cellForItem(at: indexPath)?.backgroundColor = UIColor.highlightCellGreen()
    if let cell = collectionView.cellForItem(at: indexPath) as? ClientListDateCollectionViewCell{
        monthLabel.text = cell.monthName
        monthLabel.text = monthLabel.text?.capitalized

}                                                                                      

I tried to select the middle cell while scrolling using the viewDidScroll() delegate. But, I wasn't able to get the output I wanted.

func scrollViewDidScroll(_ scrollView: UIScrollView) {

       let visibleCellCount = dateCollectionView.indexPathsForVisibleItems.count
       let cellCount = dateCollectionView.visibleCells.count
let visibleCells = dateCollectionView.indexPathsForVisibleItems[visibleCellCount-1/2]
      if visibleCellCount>0{
       let middle = visibleCellCount/2
       let midValue = dateCollectionView.indexPathsForVisibleItems[middle]
           dateCollectionView.selectItem(at: midValue, animated: true, scrollPosition: .centeredHorizontally)
}                                                                          

How do I go about selecting the middle cell?

edit 1: The collection view starts on the leftmost point and then scrolls to the middle i.e, today's date

Upvotes: 2

Views: 4176

Answers (5)

iPran
iPran

Reputation: 126

I was also trying to do the auto-selection of the middle visible cell of the collection view, and I got the solution, here is the solution:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// Reload Collection View
collectionView.reloadData()
// Find centre point of collection view
let visiblePoint = CGPoint(x: collectionView.center.x + collectionView.contentOffset.x, y: collectionView.center.y + collectionView.contentOffset.y)
// Find index path using centre point
guard let newIndexPath = collectionView.indexPathForItem(at: visiblePoint) else { return }
// Select the new centre item
collectionView.selectItem(at: newIndexPath, animated: true, scrollPosition: .centeredHorizontally)   }

You need to use the Scroll view delegate function, scrollViewDidEndDecelerating. Reload the collection view first. Second, find the center visible point of the collection view. Third, using the center visible point, find the indexPath of collection view and finally use the index to select the item in the collection view.

I know I answered this question a little late, still thinking that it will be helpful for someone.

Cheers!

Upvotes: 0

Sereysophea Eap
Sereysophea Eap

Reputation: 111

I think you can use a method to get the center point of collection view, and use this value to get the the middle of visible cell.

let centerPoint = self.view.convert(collectionView.center, to: collection)

Here is an example I did it with a tableView. You can apply it to your collection view with the same approach.

class ViewController: UIViewController {
  @IBOutlet weak var tableView: UITableView!
  var dataSource = Array(1...31)
  var centerIndex: IndexPath?

  func setCellSelected(cell: UITableViewCell, _ selected: Bool) {
    cell.contentView.backgroundColor = selected ? .green : .white
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    dataSource.count
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CELL")
    cell?.textLabel?.text = String(dataSource[indexPath.row])

    let center = self.view.convert(tableView.center, to: tableView)
    if let index = tableView.indexPathForRow(at: center), let cell = cell {
      setCellSelected(cell: cell, indexPath.row == index.row)
    }
    return cell!
  }
}

extension ViewController: UITableViewDelegate {
  func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // reset the previous hight light cell
    if let centerIndex = centerIndex, let cell = tableView.cellForRow(at: centerIndex) {
      setCellSelected(cell: cell, false)
    }
    // set hight light to a new center cell
    let center = self.view.convert(tableView.center, to: tableView)
    if let index = tableView.indexPathForRow(at: center), let cell = tableView.cellForRow(at: index) {
      setCellSelected(cell: cell, true)
      centerIndex = index
    }
  }
}

Upvotes: 0

Sereysophea Eap
Sereysophea Eap

Reputation: 111

Suppose that you have the horizontal of displaying, and you want to have the auto scroll to the center of your item in datasource.

  1. Creating a method and calling it immediately after your collection view is completely configured:

    func scrollToCenterIndex() {
        let centerIndex = LIST_OF_YOUR_DATA_SOURCE.count / 2
        let indexPath = IndexPath(item: centerIndex, section: 0)
        self.collectionView.scrollToItem(at: indexPath,
                                         at: .right,
                                         animated: false)
     }
    
  2. Inside the method:

    public func collectionView(_ collectionView: UICollectionView,
                                 cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CELL,
                                                            for: indexPath) as? CustomCell else {
                                                              fatalError("Cannot create cell")
        }
    
        If indexPath.row == LIST_OF_YOUR_DATA_SOURCE.count / 2  {
            // perform your hight light color to the cell
        } else {
            // reset your hight light color to default color
        }
        let model = LIST_OF_YOUR_DATA_SOURCE[indexPath.row] 
        cell.configure(model)
    
        return cell
      }
    

Upvotes: 0

Desdenova
Desdenova

Reputation: 5377

Disable multiple selection (or selection entirely?) to make things easier.

collectionView.allowsMultipleSelection = false

On scrollViewDidScroll(_:) get the center point of the screen as CGpoint.

let center = collectionView.center

Use that information to get the index path of the center item

let indexPath = collectionView.indexPathForItem(at: center)

Select the item

collectionView.selectItem(at: indexPath, animated: true, scrollPosition: .top)

Upvotes: 0

Meesum Naqvi
Meesum Naqvi

Reputation: 186

You can use delegate of UICollectionView (i.e: didHighlightItemAtIndexPath). just make sure to call collection view delegates on your desired time by calling reload function

self.collectionView.reloadData()

and in you collection view delegate just do this

 func collectionView(collectionView: UICollectionView, didHighlightItemAtIndexPath indexPath: NSIndexPath){

    var cell : UICollectionViewCell = UICollectionViewCell()

    self.collectionView.cellForItemAtIndexPath = indexPath
    //change highlighted color as of your need
    cell.view.backgroundColor = UIColor.init(red: 25, green: 118, blue: 210).cgColor
    }

This will highlight you selected item

Upvotes: 1

Related Questions