UICollectionView具有静态焦点项的水平滚动

时间:2018-06-28 05:02:02

标签: swift uicollectionview uikit tvos apple-tv

我正在尝试在tvOS上的UITableViewCell中创建一个可水平滚动的UICollectionView,并且已经实现了我的目标。

下一步,我需要将焦点移到UICollectionView中的下一个项目,但是整个项目堆栈应向左或向右移动一个位置,但是焦点将保持在视觉上是“第一项”。

下面是我希望实现的一些ASCII图:

Scenario 1, before focus shifts
     ---------------------
1.   | v   v   v   v   v |
2.   |[v]  v   v   v   v |
3.   | v   v   v   v   v |
     ---------------------

Scenario 1, after focus shifts
     ---------------------
1.   | v   v   v   v   v |
2.   | v  [v]  v   v   v |
3.   | v   v   v   v   v |
     ---------------------

上面的方案1 是默认的行为,焦点转移到UICollectionView中的下一项。

Scenario 2, before focus shifts
     ---------------------
1.   | v   v   v   v   v |
2.   |[v]  v   v   v   v |
3.   | v   v   v   v   v |
     ---------------------

Scenario 2, after focus shifts
     ---------------------
1.   | v   v   v   v   v |
2. v |[v]  v   v   v     |
3.   | v   v   v   v   v |
     ---------------------

方案2 中,我在遥控器上滑动以选择UICollectionView中的下一个项目之后,焦点应保持在左侧,但焦点下方的项目应移动一个。

>

有人对如何实现这一目标有任何暗示吗?

我已经阅读了UICollectionView中粘性列上的帖子,但是我认为这不完全是粘性列吗?

3 个答案:

答案 0 :(得分:0)

最近我不得不为此做一个项目。这是我用的:

 override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
    if let focusView = context.nextFocusedView as? UICollectionViewCell, let indexPath = collection.indexPath(for: focusView) {

        collection.isScrollEnabled = false
        coordinator.addCoordinatedAnimations({
            self.collection.scrollToItem(at: indexPath, at: .left, animated: true)
        }, completion: nil)
    }
}

答案 1 :(得分:0)

从 tvOS 13 开始,您可以使用 UICollectionViewCompositionalLayout 的 UICollectionLayoutSectionOrthogonalScrollingBehavior(.groupPagin) 来处理水平滚动的静态焦点。 只需在组中添加一项即可!

private func createCollectionViewLayout() -> UICollectionViewLayout {
        
    let sectionProvider = {
        (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
            let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
            let item = NSCollectionLayoutItem(layoutSize: itemSize)
            let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(100), heightDimension: .absolute(100))
            let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
            let section = NSCollectionLayoutSection(group: group)

            section.orthogonalScrollingBehavior = .groupPaging

            return section
        }
    return UICollectionViewCompositionalLayout(sectionProvider: sectionProvider)
}

答案 2 :(得分:0)

UICollectionViewDelegate 方法在焦点移动期间调用。因此,要解决您的任务,您需要操作 UICollectionView 的 (UIScrollView) 内容偏移量。要实现类似“本机”的方式,您需要:

实现UICollectionViewDelegate方法collectionView:didUpdateFocusInContext:withAnimationCoordiantor,保存下一个聚焦单元格origin(x,y),并在UIScrollViewDelegate方法scrollViewWillEndDragging:withVelocity:targetContentOffset:中设置新目标指向焦点单元格原点的内容偏移量。

@interface CLViewController () <UICollectionViewDelegate, UICollectionViewDataSource>
@property (nonatomic) CGPoint focusedCellPosition;
@end

@implementation CLViewController
- (void)collectionView:(UICollectionView *)collectionView didUpdateFocusInContext:(UICollectionViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator {
    NSIndexPath *next = context.nextFocusedIndexPath;
    self.focusedCellPosition = [collectionView cellForItemAtIndexPath:next].frame.origin;
}

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
    *targetContentOffset = self.focusedCellPosition;
}
@end