将 UICollectionView 集中在 tvOS 上的行
Centering UICollectionView focused row on tvOS
我的 tvOS 应用程序中有一个 UICollectionView
,其中填充了多个 UICollectionViewCell
,而这些 UICollectionViewCell
又包含一个 UICollectionView
,里面有自己的项目。
容器 UICollectionView
垂直滚动,而内部 UICollectionView
水平滚动。顶级 UICollectionViewCell
s 的焦点被禁用,并被传递到内部 UICollectionView
.
的项目中
它的样子,类似于:
-------------------
| |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
| |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
| |
-------------------
我在这里想要实现的是,当焦点出现在 [=15= 的垂直中心线下方的行上时,该行应该在 UICollectionView
中垂直居中。
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|
| |
-------------------
有人 comment/suggestion 告诉我如何实现吗?
编辑: 基于另一个 ,我尝试实现以下 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)
}
}
您可以像这样使用 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)
}
}
}
我的 tvOS 应用程序中有一个 UICollectionView
,其中填充了多个 UICollectionViewCell
,而这些 UICollectionViewCell
又包含一个 UICollectionView
,里面有自己的项目。
容器 UICollectionView
垂直滚动,而内部 UICollectionView
水平滚动。顶级 UICollectionViewCell
s 的焦点被禁用,并被传递到内部 UICollectionView
.
它的样子,类似于:
-------------------
| |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
| |
| --------------- |
| | xxxx xxxx xx| |
| | xxxx xxxx xx| |
| --------------- |
| |
-------------------
我在这里想要实现的是,当焦点出现在 [=15= 的垂直中心线下方的行上时,该行应该在 UICollectionView
中垂直居中。
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|
| |
-------------------
有人 comment/suggestion 告诉我如何实现吗?
编辑: 基于另一个 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)
}
}
您可以像这样使用 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)
}
}
}