首页 > 解决方案 > 在 tvOS 上居中 UICollectionView 重点行

问题描述

我的 tvOS 应用程序中有一个UICollectionView填充了几个UICollectionViewCells 的 s,而这些 s 又包含一个UICollectionView带有它们自己的项目的内部。

容器UICollectionView垂直滚动,而内部UICollectionView滚动水平。顶级UICollectionViewCells 禁用焦点,并传递到内部 s 中的项目UICollectionView

它看起来像这样:

-------------------
|                 |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
|                 |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
|                 |
-------------------

我在这里想要实现的是,当焦点出现UICollectionViewUICollectionView.

Before centering vertically
-------------------
| 1xxx xxxx xxxx x|
| 1xxx xxxx xxxx x|
|                 |
| 2xxx xxxx xxxx x|
| 2xxx xxxx xxxx x|
|                 |
| 3xxx xxxx xxxx x| <-
| 3xxx xxxx xxxx x| <-
|                 |
| 4xxx xxxx xxxx x|
-------------------

=

After centering vertically
-------------------
|                 |
| 2xxx xxxx xxxx x|
| 2xxx xxxx xxxx x|
|                 |
| 3xxx xxxx xxxx x|
| 3xxx xxxx xxxx x|
|                 |
| 4xxx xxxx xxxx x|
| 4xxx xxxx xxxx x|
|                 |
-------------------

有没有人对我如何实现这一点有评论/建议?

编辑:基于另一个SO post,我尝试实现以下UICollectionViewDelegate功能,但它似乎对我不起作用:

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        if let indexPath = context.nextFocusedIndexPath,
            let _ = collectionView.cellForItem(at: indexPath) {
            collectionView.contentInset.top = max((collectionView.frame.height - collectionView.contentSize.height) / 2, 0)
        }
    }

编辑:在下面建议的答案导致一些试验和错误之后,我已经让它与以下代码一起使用:

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
        if let indexPath = context.nextFocusedIndexPath {
            collectionView.isScrollEnabled = false

            coordinator.addCoordinatedAnimations({
                self.collectionView.scrollToItem(at: indexPath, at: .centeredVertically, animated: true)
            }, completion: nil)
        }
    }

标签: swiftuicollectionviewuicollectionviewcelltvos

解决方案


您可以像这样使用 scrollToItemAtIndexPath 方法:

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
    if let indexPath = context.nextFocusedIndexPath,
        let _ = collectionView.cellForItem(at: indexPath) {
        self.collectionView.scrollToItem(at: indexPath, at: 
         .centeredVertically, animated: true)
    }
}

已编辑

您必须使用可访问性属性或其他方式从单元格中提取 indexPath,而不是像这样滚动到该 indexPath:

override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
    if let nextCell = context.nextFocusedView as? ScrumCollectionViewCell {
        let index = Int(nextCell.accessibilityHint!)!
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { // 2
            self.collectionView.scrollToItem(at: IndexPath(item: index, section: 0), at: .centeredVertically, animated: true)
        }
    }
}

推荐阅读