自动选择集合视图的中间可见单元格

Posted

技术标签:

【中文标题】自动选择集合视图的中间可见单元格【英文标题】:Auto Select Middle Visible Cell Of Collection View 【发布时间】:2019-10-22 09:46:56 【问题描述】:

我正在尝试在任何给定时间选择并突出显示集合视图中可见单元格的中间单元格。有问题的集合视图显示前后六个月的天数。

我尝试过使用滚动视图委托和集合视图委托。但所有的工作都是在didSelectItem() 集合视图委托中选择并突出显示代码。

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

                                                                                      

我尝试在使用viewDidScroll() 委托滚动时选择中间单元格。但是,我无法获得我想要的输出。

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)
                                                                          

如何选择中间单元格?

编辑1:集合视图从最左边开始,然后滚动到中间,即今天的日期

【问题讨论】:

let middle = visibleCellCount/2 这是什么!!! 没那么简单 @SPatel 我很乐意学习如何正确地做到这一点。我刚开始用swift。请帮助我了解它应该如何完成 我不明白你为什么要这样做?有截图吗? @Nullable 我正在尝试使用显示日期的集合视图和集合下方的标签显示所选日期的当前月份的日期选择器 【参考方案1】:

您可以使用 UICollectionView 的委托(即:didHighlightItemAtIndexPath)。只需确保通过调用 reload 函数在您想要的时间调用集合视图代表

self.collectionView.reloadData()

在你的集合视图委托中这样做

 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
    

这将突出显示您选择的项目

【讨论】:

我想在滚动集合视图时保持可见单元格的中间单元格被选中并突出显示。您提供的答案仅突出显示给定的单元格。 因此,您可以使用集合视图的委托函数返回可见索引数组(即:public func indexPathsForVisibleItems())。那么您必须将数组计数除以 2,这将返回中间索引。然后只需设置 cell.setSelected = true。并设置突出显示。这可能会对你有所帮助。【参考方案2】:

禁用多重选择(或完全选择?)以使事情变得更容易。

collectionView.allowsMultipleSelection = false

scrollViewDidScroll(_:) 上获取屏幕中心点为CGpoint

let center = collectionView.center

使用该信息获取中心项的索引路径

let indexPath = collectionView.indexPathForItem(at: center)

选择项目

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

【讨论】:

集合只是在不选择单元格的情况下继续滚动,并在断点处观察,它表明该点的索引路径为零 尝试将点转换为集合视图的坐标空间。 let converted = self.view.convert(center, to: self.collectionView) 并使用这个新点。【参考方案3】:

假设您有水平显示,并且您希望自动滚动到数据源中项目的中心。

    创建一个方法并在你的集合视图完全配置后立即调用它:

    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)
     
    

    方法内部:

    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
      
    

【讨论】:

我已经实现了类似的东西。我想要的是,每次滚动集合视图时,我都需要选择并突出显示中间单元格 我不太了解您需要什么。所以这就是你需要的,对吧?假设您有 23 个项目,屏幕中显示的单元格数量为 11 个项目 - 索引 0 到 10,因此中间项目将位于索引 5 处,即选中时的高亮。滚动到一点后,项目将显示从索引 1 到 11,中间将在索引 6 处高亮,索引 5 将被重置,依此类推。是否符合您的需要? 我添加了一个带有表格视图的示例。希望对您有所帮助。【参考方案4】:

我认为您可以使用一种方法来获取集合视图的中心点,并使用该值来获取可见单元格的中间。

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

这是一个我用 tableView 做的例子。您可以使用相同的方法将其应用于您的集合视图。

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
    
  

【讨论】:

【参考方案5】:

我也在尝试自动选择集合视图的中间可见单元格,我得到了解决方案,这里是解决方案:

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)   

您需要使用滚动视图委托函数,scrollViewDidEndDecelerating。首先重新加载集合视图。其次,找到集合视图的中心可见点。第三,使用中心可见点,找到collection view的indexPath,最后使用index选择collection view中的item。

我知道我回答这个问题有点晚了,仍然认为它会对某人有所帮助。

干杯!

【讨论】:

这条线是做什么的? scrollingDelegate?.scrollViewDidEndDecelerating(scrollView) @krishnaravichander 请忽略那行兄弟,它会正常工作的。我正在使用这行代码来满足我的要求,在这里意外添加(我现在将其删除)。感谢您的评论。

以上是关于自动选择集合视图的中间可见单元格的主要内容,如果未能解决你的问题,请参考以下文章

启用分页时将水平可滚动集合视图的单元格居中并使其他单元格部分可见

取消选择当前不可见的单元格

如何从集合视图中的不可见单元格中删除自定义视图

集合视图中的单元格不可见

在集合视图中找到中间单元格并更改其内容

当作为子视图添加到集合视图单元格时,滚动视图中的内容不可见