将 collectionview 中的活动单元格保存在一个地方
Keep active cell in collectionview in one place
我正在开发一个 tvOS 应用程序,我希望 collectionView 的活动单元格始终位于同一位置。换句话说,我不希望活动单元格通过我的 collectionView,但我希望 collectionView 通过我的活动单元格。
下图中的示例。活动标签始终位于屏幕中央,而您可以滚动 collectionView 以获得不同的活动标签。
基本上是一个自定义 UI 的 pickerview。但遗憾的是tvOS上没有提供iOS的pickerview...
我已经调查过 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
}
}
打印时偏移量returns 增量为100。标签的高度为 90,间距为 10。所以我认为这是正确的,尽管它一直运行到 2400(最后一个标签)。
关于从这里到哪里去的任何想法?
我在 tvOS 上工作已经一年多了,但我记得它应该相当简单,只需一个简单的技巧。使用更新后的 api 可能有更好的方法来执行此操作,但这就是我所做的。
1) 禁止滚动集合视图 isScrollEnabled = false
2) In delegate, optional public func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator), get nextFocusedIndexPath 并计算单元格的偏移量在集合视图。
3) 使用偏移量,在委托回调中手动设置滚动动画。
我找到了旧的 post 我有了一个想法。
How to center UICollectionViewCell that was focused?
我最终做的与线程中的答案有些不同,但这是一个很好的提示。
好的,加上@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()
})
}
}
我正在开发一个 tvOS 应用程序,我希望 collectionView 的活动单元格始终位于同一位置。换句话说,我不希望活动单元格通过我的 collectionView,但我希望 collectionView 通过我的活动单元格。
下图中的示例。活动标签始终位于屏幕中央,而您可以滚动 collectionView 以获得不同的活动标签。
基本上是一个自定义 UI 的 pickerview。但遗憾的是tvOS上没有提供iOS的pickerview...
我已经调查过 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
}
}
打印时偏移量returns 增量为100。标签的高度为 90,间距为 10。所以我认为这是正确的,尽管它一直运行到 2400(最后一个标签)。
关于从这里到哪里去的任何想法?
我在 tvOS 上工作已经一年多了,但我记得它应该相当简单,只需一个简单的技巧。使用更新后的 api 可能有更好的方法来执行此操作,但这就是我所做的。
1) 禁止滚动集合视图 isScrollEnabled = false
2) In delegate, optional public func collectionView(_ collectionView: UICollectionView, didUpdateFocusIn context: UICollectionViewFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator), get nextFocusedIndexPath 并计算单元格的偏移量在集合视图。
3) 使用偏移量,在委托回调中手动设置滚动动画。
我找到了旧的 post 我有了一个想法。
How to center UICollectionViewCell that was focused?
我最终做的与线程中的答案有些不同,但这是一个很好的提示。
好的,加上@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()
})
}
}