如何从collectionView中的第二项开始?

Posted

技术标签:

【中文标题】如何从collectionView中的第二项开始?【英文标题】:How to start from the second item in collectionView? 【发布时间】:2019-03-06 14:00:20 【问题描述】:

现在我有一个集合视图,它总是从第一个元素开始,但我希望用户完成关卡,一旦他们完成,集合视图应该从第二个元素开始,如下图所示。

一段时间后,当关卡完成时从第二个元素开始,如下所示:

您知道如何做到这一点吗?到目前为止,我已经这样做了。

  public protocol SnapLikeDataDelegate: class 
func cellSelected(_ index: Int)


 public class SnapLikeDataSource<Cell: UICollectionViewCell>: NSObject, UICollectionViewDelegate, UICollectionViewDataSource where Cell: SnapLikeCell 

enum NearestPointDirection: Int 
    case any
    case left
    case right

private var scrollVelocity: CGFloat = 0.0
private var selectedItem: Int = 0

public weak var delegate: SnapLikeDataDelegate?
public var items: [Cell.Item] = []
public var images: [Cell.Image] = []

private let selectionFB = UISelectionFeedbackGenerator()

private weak var collectionView: UICollectionView?
private var collectionViewCenter: CGFloat
private let cellSize: SnapLikeCellSize

public init(collectionView: UICollectionView, cellSize: SnapLikeCellSize) 
    self.collectionView = collectionView
    self.collectionViewCenter = collectionView.bounds.width / 2
    self.cellSize = cellSize


// MARK: - Animation:

public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) 
    if self.selectedItem == Int.max  return 

    let previousSelectedIndex: Int = selectedItem
    // add a placeholder value for selectedItem while scrolling
    selectedItem = Int.max

    reloadCell(at: IndexPath(item: previousSelectedIndex, section: 0), withSelectedState: false)


public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) 
    scrollVelocity = velocity.x

    if scrollVelocity == 0 
        targetContentOffset.pointee = offset(forCenterX: targetContentOffset.pointee.x + collectionViewCenter, with: .any)
    
    if scrollVelocity < 0 
        targetContentOffset.pointee = offset(forCenterX: targetContentOffset.pointee.x + collectionViewCenter, with: .left)
     else if scrollVelocity > 0 
        targetContentOffset.pointee = offset(forCenterX: targetContentOffset.pointee.x + collectionViewCenter, with: .right)
    



public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) 
    reloadCell(at: IndexPath(item: selectedItem, section: 0), withSelectedState: true)
    selectionFB.selectionChanged()
    delegate?.cellSelected(selectedItem)


/// Reload cell so it becomes selected or unselected
public func reloadCell(at indexPath: IndexPath, withSelectedState selected: Bool) 
    if let cell = collectionView?.cellForItem(at: indexPath) 
        cell.isSelected = selected
    


public func selectItem(_ indexPath: IndexPath) 
    perform(#selector(collectionView(_:didSelectItemAt:)),
            with: collectionView,
            with: indexPath)


// Calculate the offset to the center from the nearest cell
func offset(forCenterX centerX: CGFloat, with direction: NearestPointDirection) -> CGPoint 
    let leftNearestCenters = nearestLeftCenter(forCenterX: centerX)
    let leftCenterIndex: Int = leftNearestCenters.index
    let leftCenter: CGFloat = leftNearestCenters.value
    let rightNearestCenters = nearestRightCenter(forCenterX: centerX)
    let rightCenterIndex: Int = rightNearestCenters.index
    let rightCenter: CGFloat = rightNearestCenters.value
    var nearestItemIndex: Int = Int.max
    switch direction 
    case .any:
        if leftCenter > rightCenter 
            nearestItemIndex = rightCenterIndex
         else 
            nearestItemIndex = leftCenterIndex
        
    case .left:
        nearestItemIndex = leftCenterIndex
    case .right:
        nearestItemIndex = rightCenterIndex
    
    selectedItem = nearestItemIndex
    return CGPoint(x: CGFloat(nearestItemIndex) * cellSize.normalWidth, y: 0.0)


/// Getting the nearest cell attributes on the left
func nearestLeftCenter(forCenterX centerX: CGFloat) -> (index: Int, value: CGFloat) 
    let nearestLeftElementIndex: CGFloat = (centerX - collectionViewCenter - cellSize.centerWidth + cellSize.normalWidth) / cellSize.normalWidth
    let minimumLeftDistance: CGFloat = centerX - nearestLeftElementIndex * cellSize.normalWidth - collectionViewCenter - cellSize.centerWidth + cellSize.normalWidth
    return (Int(nearestLeftElementIndex), minimumLeftDistance)


/// Getting the nearest cell attributes on the right
func nearestRightCenter(forCenterX centerX: CGFloat) -> (index: Int, value: CGFloat) 
    let nearestRightElementIndex: Int = Int(ceilf(Float((centerX - collectionViewCenter - cellSize.centerWidth + cellSize.normalWidth) / cellSize.normalWidth)))
    let minimumRightDistance: CGFloat = CGFloat(nearestRightElementIndex) * cellSize.normalWidth + collectionViewCenter - centerX - cellSize.centerWidth + cellSize.normalWidth
    return (nearestRightElementIndex, minimumRightDistance)


// MARK : - Delegate

@objc public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    collectionView.deselectItem(at: indexPath, animated: false)

    scrollViewWillBeginDragging(collectionView)
    selectedItem = indexPath.item

    let layout = collectionView.collectionViewLayout as! SnapLikeCollectionViewFlowLayout
    let x: CGFloat = CGFloat(selectedItem) * cellSize.normalWidth
    layout.ignoringBoundsChange = true
    collectionView.setContentOffset(CGPoint(x: x, y: 0), animated: true)
    layout.ignoringBoundsChange = false

    perform(#selector(self.scrollViewDidEndDecelerating), with: collectionView, afterDelay: 0.3)



  public func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1


public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return items.count


public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: Cell.self), for: indexPath) as! Cell
    cell.item = items[indexPath.item]
    cell.image = images[indexPath.item]
    return cell

在我的视图控制器中,我这样做:

         var logoImage: [UIImage] = [
         UIImage(named: "1") ?? UIImage(named: "1")!,
         UIImage(named: "2") ?? UIImage(named: "1")!,
         UIImage(named: "3") ?? UIImage(named: "1")!,
         UIImage(named: "2") ?? UIImage(named: "1")!,
         UIImage(named: "1") ?? UIImage(named: "1")!
]

    dataSource?.items = ["1", "2", "3", "4", "F"]
    dataSource?.images = logoImage

【问题讨论】:

How to scroll to a particluar index in collection view in swift的可能重复 【参考方案1】:

我用过这个功能:

 collectionView.scrollToItem(at: IndexPath(item: 3, section: 0), at: [], animated: false)

它的工作原理是,一旦应用启动,CollectionView 就会显示项目集中的第三个元素。

【讨论】:

【参考方案2】:

您可以在 [self.collectionView reloadData] 之后简单地使用它

let index = 1 // item selected
yourCollectionView.selectItemAtIndexPath(NSIndexPath(forItem: index, inSection: 0), animated: false, scrollPosition: .None)

其中index 是所选元素的索引号。

【讨论】:

也许之后:yourCollectionView.reloadData()

以上是关于如何从collectionView中的第二项开始?的主要内容,如果未能解决你的问题,请参考以下文章

用数据框的行值替换子列表中的第二项

插入排序

markdown列表

当collectionview中的第一个单元格聚焦时无法聚焦uibutton

如何访问列表中的第二个参数?

算法:插入排序详解--为什么从第二项开始,而不是第一项