当前位置:  开发笔记 > IOS > 正文

设备轮换后的UICollectionView contentOffset

如何解决《设备轮换后的UICollectionViewcontentOffset》经验,为你挑选了2个好方法。

您可以通过实现UICollectionViewDelegate方法来完成此操作collectionView(_:targetContentOffsetForProposedContentOffset:):

在布局更新期间,或在布局之间转换时,集合视图调用此方法,使您有机会更改要在动画结束时使用的建议内容偏移.如果布局或动画可能导致项目以不适合您的设计的方式定位,则可能会返回新值.

或者,如果您已经子类化了UICollectionViewLayout,则可以targetContentOffset(forProposedContentOffset:)在布局子类中实现,这可能更方便.

在您的方法实现中,计算并返回内容偏移量,该偏移量将导致中心单元格位于集合视图的中心.如果您的单元格大小是固定的,则应该简单地撤消由其他UI元素(例如状态栏和/或导航栏的消失帧)导致的内容偏移的更改.

如果您的单元格大小因设备方向而异:

    在设备旋转之前,通过调用indexPathForItem(at:)集合视图来获取并保存中心单元的索引路径,将内容偏移量(加上集合视图的可见边界的高度的一半)作为点传递.

    实现其中一种targetContentOffset(forProposedContentOffset:)方法.通过layoutAttributesForItem(at:)使用保存的索引路径调用来检索中心单元的布局属性.目标内容偏移量是该项目框架的中间位置(减少了集合视图可见边界高度的一半).

第一步可以在视图控制器中viewWillTransition(to:with:)或中实现scrollViewDidScroll().它也可以在你的布局对象实施的prepareForAnimatedBoundsChange(),或者在invalidateLayout(with:)检查引起设备取向的变化范围变更后.(在这种情况下,您还需要确保shouldInvalidateLayout(forBoundsChange:)返回true.)

您可能需要针对内容插入,单元格间距或应用程序特定的其他事项进行调整.



1> jamesk..:

您可以通过实现UICollectionViewDelegate方法来完成此操作collectionView(_:targetContentOffsetForProposedContentOffset:):

在布局更新期间,或在布局之间转换时,集合视图调用此方法,使您有机会更改要在动画结束时使用的建议内容偏移.如果布局或动画可能导致项目以不适合您的设计的方式定位,则可能会返回新值.

或者,如果您已经子类化了UICollectionViewLayout,则可以targetContentOffset(forProposedContentOffset:)在布局子类中实现,这可能更方便.

在您的方法实现中,计算并返回内容偏移量,该偏移量将导致中心单元格位于集合视图的中心.如果您的单元格大小是固定的,则应该简单地撤消由其他UI元素(例如状态栏和/或导航栏的消失帧)导致的内容偏移的更改.

如果您的单元格大小因设备方向而异:

    在设备旋转之前,通过调用indexPathForItem(at:)集合视图来获取并保存中心单元的索引路径,将内容偏移量(加上集合视图的可见边界的高度的一半)作为点传递.

    实现其中一种targetContentOffset(forProposedContentOffset:)方法.通过layoutAttributesForItem(at:)使用保存的索引路径调用来检索中心单元的布局属性.目标内容偏移量是该项目框架的中间位置(减少了集合视图可见边界高度的一半).

第一步可以在视图控制器中viewWillTransition(to:with:)或中实现scrollViewDidScroll().它也可以在你的布局对象实施的prepareForAnimatedBoundsChange(),或者在invalidateLayout(with:)检查引起设备取向的变化范围变更后.(在这种情况下,您还需要确保shouldInvalidateLayout(forBoundsChange:)返回true.)

您可能需要针对内容插入,单元格间距或应用程序特定的其他事项进行调整.


遗憾的是,当拆分视图发生变化时,不会在iPad上调用`targetContentOffsetForProposedContentOffset`.这意味着不能普遍处理旋转和宽度变化.

2> 0rt..:

这是实施jamesk solutuion在swift

在您的ViewController中:

fileprivate var prevIndexPathAtCenter: IndexPath?

fileprivate var currentIndexPath: IndexPath? {
    let center = view.convert(collectionView.center, to: collectionView)
    return collectionView.indexPathForItem(at: center)
}

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
    super.willTransition(to: newCollection, with: coordinator)

    if let indexAtCenter = currentIndexPath {
        prevIndexPathAtCenter = indexAtCenter
    }
    collectionView.collectionViewLayout.invalidateLayout()
}

在UICollectionViewDelegateFlowLayout中:

func collectionView(_ collectionView: UICollectionView, targetContentOffsetForProposedContentOffset proposedContentOffset: CGPoint) -> CGPoint {

    guard let oldCenter = prevIndexPathAtCenter else {
        return proposedContentOffset
    }

    let attrs =  collectionView.layoutAttributesForItem(at: oldCenter)

    let newOriginForOldIndex = attrs?.frame.origin

    return newOriginForOldIndex ?? proposedContentOffset
}

推荐阅读
跟我搞对象吧
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有