Как начать со второго элемента в collectionView? - PullRequest
1 голос
/ 06 марта 2019

Прямо сейчас у меня есть представление коллекции, которое всегда начинается с 1-го элемента, но я хочу, чтобы пользователи проходили уровни, и как только они закончили, представление коллекции должно начинаться со второго элемента, как на рисунке ниже.

enter image description here

Через некоторое время, когда уровень заканчивается, чтобы начать со второго элемента, как это:

enter image description here

У вас есть идея, как это сделать? Теперь я уже сделал это.

  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
}

В моем viewcontroller я делаю это:

         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

Ответы [ 3 ]

3 голосов
/ 06 марта 2019

Я использовал эту функцию:

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

И она работает, после запуска приложения CollectionView показывает 3-й элемент в наборе элементов.

0 голосов
/ 06 марта 2019

Можете ли вы попробовать это,

collectionView.contentOffset.y = your collectionViewCellHeight

Установите это свойство после перезагрузки collectionView.

0 голосов
/ 06 марта 2019

Вы можете просто использовать это после [self.collectionView reloadData]

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

где index - порядковый номер для выбранного элемента.

...