在特定索引路径处启动UICollectionView

Zac*_*ack 42 paging ios uicollectionview

我目前有一个集合视图,可以进行水平分页,其中每个单元格都是全屏的.我想要做的是集合视图在显示时从特定索引开始.

现在我正在使用scrollToItemAtIndexPath:atScrollPosition:animated:将动画设置为NO,但仍然可以先加载第一个索引,然后才能滚动到特定项目.我似乎只能在ViewDidAppear中使用此方法,因此它显示第一个单元格,然后闪烁到我想要显示的单元格.我通过隐藏集合视图来隐藏它,直到滚动完成但看起来并不理想.

除了我描述的方式之外,还有更好的方法吗?

谢谢!

ssc*_*ale 54

所以我用一种不同的方式解决了这个问题,使用了这种UICollectionViewDelegate方法和一次性Bool:

斯威夫特2:

var onceOnly = false

internal func collectionView(collectionView: UICollectionView, willDisplayCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
    if !onceOnly {
        let indexToScrollTo = NSIndexPath(forRow: row, inSection: section)
        self.problemListCollectionView.scrollToItemAtIndexPath(indexToScrollTo, atScrollPosition: .Left, animated: false)
        onceOnly = true
    }

}
Run Code Online (Sandbox Code Playgroud)

斯威夫特3:

  var onceOnly = false

  internal func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
    if !onceOnly {
      let indexToScrollTo = IndexPath(item: row, section: section)
      self.problemListCollectionView.scrollToItem(at: indexToScrollTo, at: .left, animated: false)
      onceOnly = true
    }
  }
Run Code Online (Sandbox Code Playgroud)

这个代码在任何动画发生之前执行(所以它真的加载到这一点),这比试图调用更好viewDidAppear,而且我没有成功viewWillAppear.


vic*_*ica 16

为了解决这个问题,我部分使用了温室的答案.

/// Edit
var startIndex: Int! = 0

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    collectionView.setNeedsLayout()
    collectionView.layoutIfNeeded()

    collectionView.scrollToItemAtIndexPath(
        NSIndexPath(forItem: 0, inSection: startIndex),
        atScrollPosition: .None,
        animated: false)
 }
Run Code Online (Sandbox Code Playgroud)

问题似乎是错误的collectionView大小.设置布局后scrollToItemAtIndexPath产生所需的结果.

似乎这个问题只在a Collection View内部使用时才会存在UIViewController.


小智 7

受其他人启发的更简单的解决方案:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    DispatchQueue.main.async {
        self.collectionView.scrollToItem(at: lastIndexPath, section: 0), at: .centeredHorizontally, animated: false)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果将代码放在 DispatchQueue.main.async 块中,它将起作用。


kem*_*ica 5

Swift 3.0经过测试和运行.

var onceOnly = false
    internal func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        if !onceOnly {
            //set the row and section you need.
            let indexToScrollTo = IndexPath(row: 1, section: indexPath.section)
            self.fotmCollectionView.scrollToItem(at: indexToScrollTo, at: .left, animated: false)
            onceOnly = true
        }
    }
Run Code Online (Sandbox Code Playgroud)


Log*_*ire 5

不幸的是,这些现有答案中的每一个至少部分是错误的,或者没有回答所提出的确切问题。我与一位同事共同解决了这个问题,而这些答复都没有帮助他。

您需要做的就是将不带动画的内容偏移设置为正确的内容偏移,然后调用重新加载数据。(或者,如果尚未完全加载,请跳过reloadData调用。)如果您从不希望创建第一个单元格,则应在viewDidLoad中执行此操作。

该答案假定集合视图水平滚动,并且单元格的大小与视图相同,但是如果您想垂直滚动或单元格的大小不同,则概念相同。同样,如果您的CollectionView有多个部分,则必须做更多的数学运算才能计算出内容偏移量,但是概念仍然相同。

func viewDidLoad() {
    super.viewDidLoad()
    let pageSize = self.view.bounds.size
    let contentOffset = CGPoint(x: pageSize.width * self.items.count, y: 0)
    self.collectionView.setContentOffset(contentOffset, animated: false)
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是公认的答案。奇迹般有效! (2认同)
  • 我认为偏移内容与转到索引并不相同。 (2认同)
  • 这是一个非常好的解决方案,谢谢。正是我所需要的。仅在我的具体实现中,我在其他地方使用了它而不是 viewDidLoad ,无论如何它效果很好。 (2认同)

Ste*_*aul 2

将 indexPath 从第一个 VC 传递到 DidSelectItemAtIndexPath 方法中的集合视图。在集合视图的 viewDidLoad 中,使用方法scrollToItemAtIndexPath:atScrollPosition:animated:Set animatedtoNOatScrollPositionto UICollectionViewScrollPositionNone。像这样:

[self.collectionView scrollToItemAtIndexPath:self.indexPathFromVC atScrollPosition:UICollectionViewScrollPositionNone animated:NO];
Run Code Online (Sandbox Code Playgroud)