将活动单元保存在collectionview中的一个位置

时间:2017-08-17 21:33:47

标签: swift xcode uicollectionview tvos flowlayout

我正在开发一个tvOS应用程序,我希望collectionView的活动单元始终处于相同的位置。换句话说,我不希望活动单元格通过我的collectionView但我希望collectionView通过我的活动单元格。

以下图片中的示例。活动标签始终位于屏幕的中心,而您可以滚动collectionView以在其上获得不同的活动标签。

基本上是带有自定义UI的选择器视图。但不幸的是,未在tvOS上提供iOS的挑选视图...

Active Cell

我已经调查了UICollectionViewScrollPosition.verticallyCentered。这部分让我在那里,但它还不够。如果我滚动得非常快,活动项目会在列表中向下跳跃,当我暂停时,它会一直向上滚动到中心。我真的希望活动项目始终位于屏幕的中心。

关于如何做到这一点的任何想法?

根据@HMHero回复

进行更新

好的,我试着做你告诉我的事,但不能让滚动工作正常。这可能是由于我计算了偏移量,或者因为(就像你说的那样)setContentOffset(, animated: )无效。

现在我做了以下事情,不知道从哪里开始;

禁用滚动并居中最后和第一个标签

override func viewDidLoad() {
    super.viewDidLoad()
    //Disable scrolling
    self.collectionView.isScrollEnabled = false
    //Place the first and last label in the middle of the screen
    self.countryCollectionView.contentInset.top = collectionView.frame.height * 0.5 - 45
    self.countryCollectionView.contentInset.bottom = collectionView.frame.height * 0.5 - 45
}

获取标签的位置以检索距屏幕中心的距离(偏移)

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
if let indexPath = context.nextFocusedIndexPath,
        let cell = countryCollectionView.cellForItem(at: indexPath) {
            //Get the center of the next focused cell, and convert that to position in the visible part of the (tv) screen itself
            let cellCenter = countryCollectionView.convert(cell.center, to: countryCollectionView.superview)
            //Get the center of the collectionView
            let centerView = countryCollectionView.frame.midY
            //Calculate how far the next focused cell y position is from the centerview. (Offset)
            let offset = cellCenter.y - centerView
    }
}

打印时偏移量返回100的增量值。标签'高度是90,并且间隔为10.所以我认为这是正确的,尽管它一直运行到2400(最后一个标签)。

关于从哪里去的任何想法?

2 个答案:

答案 0 :(得分:4)

自从我在tvOS上工作已经一年多了,但是我记得通过一个简单的技巧它应该相当简单。使用更新的api可能有更好的方法来做到这一点,但这就是我所做的。

1)禁用滚动集合视图isScrollEnabled = false

2)在委托中,可选的public func collectionView(_ collectionView:UICollectionView,didUpdateFocusIn context:UICollectionViewFocusUpdateContext,with coordinator:UIFocusAnimationCoordinator),获取nextFocusedIndexPath并计算单元格在集合视图中心的偏移量。

3)使用偏移量,在委托回调中手动设置滚动动画。

我找到了一个老帖子,我知道了。

How to center UICollectionViewCell that was focused?

我最终与线程中的答案有所不同,但这是一个很好的暗示。

答案 1 :(得分:0)

好的,除了@HMHero的一些指示,我已经达到了预期的效果。它涉及使用自定义动画为contentOffset设置动画。这是我的代码;

func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {

    if let previousIndexPath = context.previouslyFocusedIndexPath,
        let cell = countryCollectionView.cellForItem(at: previousIndexPath) {
        UIView.animate(withDuration: 0.3, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
            cell.contentView.alpha = 0.3
            cell.contentView.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)
        })
    }

    if let indexPath = context.nextFocusedIndexPath,
        let cell = countryCollectionView.cellForItem(at: indexPath) {
        let cellCenter = CGPoint(x: cell.bounds.origin.x + cell.bounds.size.width / 2, y: cell.bounds.origin.y + cell.bounds.size.height / 2)
        let cellLocation = cell.convert(cellCenter, to: self.countryCollectionView)
        let centerView = countryCollectionView.frame.midY
        let contentYOffset = cellLocation.y - centerView

        UIView.animate(withDuration: 0.3, delay: 0, options: UIViewAnimationOptions.curveEaseOut, animations: {
            collectionView.contentOffset.y = contentYOffset
            cell.contentView.alpha = 1.0
            cell.contentView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            self.countryCollectionView.layoutIfNeeded()
        })

    }
}