在UICollectionView滚动后获取可见项的更新IndexPath

时间:2017-12-09 11:16:50

标签: ios swift uiscrollview uicollectionview

我有一个具有不同时期(每年)的collectionView供用户选择。每个项目的大小都等于collectionView本身的大小。

@IBOutlet weak var periodCollectionView: UICollectionView!
@IBOutlet weak var itemLabel: UILabel!

let collectionValues = ["Day", "Week", "Month", "Year"]
var currentVisibleItem: Int?

override func viewDidLoad() {
    super.viewDidLoad()

}

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PeriodName", for: indexPath) as? DisplayPeriodCollectionViewCell
    else {
        fatalError("Unable to cast collection view cell as DisplayPeriodCollectionViewCell")
    }

    cell.periodName.text = collectionValues[indexPath.item]

    return cell

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let height = collectionView.frame.height
    let width = collectionView.frame.width

    return CGSize(width: width, height: height)
}

我想要做的是获取一个信息标签,以在collectionView滚动后显示当前可见项目的索引。她是代码:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {

    let centerPoint = CGPoint(x: periodCollectionView.center.x + periodCollectionView.contentOffset.x, y: 1.0)
    print("centerPoint: \(centerPoint)")

    if let currentItemIndexPath = periodCollectionView.indexPathForItem(at: centerPoint) {
        currentVisibleItem = currentItemIndexPath.item
        print("index of current item: \(currentVisibleItem!)")
        itemLabel.text = "\(currentVisibleItem!)"
    } else {
        print("could not get index of current item...")
    }

}

我添加了print语句来检查是否在运行时正确定义了值,并且它们显示一切正常。问题是标签在滚动结束后并不总是更新其文本,而是等待新的滚动发生:

enter image description here

我无法弄清楚为什么会发生这种情况 - 在scrollViewDidEndDecelerating设置断点会显示所有代码都被执行,那么标签文本有什么问题?

UPD 即可。未更新标签文本似乎是模拟器问题 - 在设备上运行时,标签更新正确。

3 个答案:

答案 0 :(得分:3)

试试这个

override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    let currentIndex = scrollView.contentOffset.x / CGFloat((itemWidth + interitemSpacing / 2))
    print(currentIndex)
}

答案 1 :(得分:2)

  

请尝试以下代码。

     

我在实际项目中使用了很多次,效果很好。

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

    let visibleIndex = Int(targetContentOffset.pointee.x / collectionView.frame.width)
    print(visibleIndex)

}

答案 2 :(得分:0)

在您的情况下,您可以使用:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

因为每个项目与集合视图的大小相同。 如果您仍想使用滚动视图委托,则应在以下委托函数中编写页面计算:

func scrollViewDidEndDragging(UIScrollView, willDecelerate: Bool)

func scrollViewDidEndDecelerating(UIScrollView)

func scrollViewDidEndScrollingAnimation(UIScrollView)