8

我正在使用UICollectionView. 当用户旋转设备时,我对UICollectionView内部执行更新

func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

我以UIViewController模态方式呈现这个并UICollectionView占据了全屏。在 内viewDidLoad,我将流布局创建为:

let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.minimumInteritemSpacing = 0
flowLayout.minimumLineSpacing = 0
photosCollectionView.isPagingEnabled = true
photosCollectionView.setCollectionViewLayout(flowLayout, animated: true)

我的尺寸也为:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return photosCollectionView.frame.size
}

当我旋转我的设备时,viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)永远不会调用,这会导致UICollectionViewLayout不更新。当我旋转设备时,我确实收到了消息:

The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.

我在网上阅读过,我可以添加:

self.automaticallyAdjustsScrollViewInsets = false

UIViewController,但这并没有影响。没有内容或部分插图UICollectionView

我也有super.viewWillTransition函数内的调用。任何人都可以帮助我解决可能导致此问题的原因吗?

4

6 回答 6

17

如果您只关心设备旋转时的布局,请使用:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    collectionView.collectionViewLayout.invalidateLayout()
    collectionView.layoutIfNeeded()
}

来自苹果文档:

public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

当视图控制器的视图的大小被其父级更改时调用此方法(即,对于根视图控制器,当其窗口旋转或调整大小时)。如果您覆盖此方法,您应该调用 super 将更改传播给子级或手动将更改转发给子级。

我想您可能会在该视图的父级上调用此函数而不调用 super

解决方法也是注册设备轮换:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}

@objc func deviceOrientationDidChange(_ notification: Notification) {
    let orientation = UIDevice.current.orientation
    print(orientation)
}
于 2017-02-10T23:36:53.840 回答
10

我想重新发布一个我留在另一个描述相同问题的线程中的答案。


人们已经解释说你必须调用super。我想添加一条信息,可以帮助那些会面对我所面临的事情的人。

场景:父 -> 子(viewWillTransition 未在子中调用)


如果您的视图控制器是视图控制器,则检查是否调用了视图控制器委托以及是否在那里调用了 super。否则它不会传播到子视图控制器!

class ParentViewController: UIViewController {

    func presentChild() {
        let child = ChildViewController()
        present(child, animated: false, compeltion: nil)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator) // If this line is missing your child will not get the delegate call in it's viewWillTransition

        // Do something
    }
}

class ChildViewController: UIViewController {

    // This method will not get called if presented from parent view controller and super is not called inside the viewViewWillTransition available there.
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
       super.viewWillTransition(to: size, with: coordinator)

       //Do something
    }
}

PS - 这发生在我身上,因为父母的代码是由其他人编写的,他们忘记调用 super。

于 2018-11-30T07:16:38.043 回答
3

我换了

func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)

经过

func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator)

它对我有用。

于 2019-12-11T09:35:31.730 回答
0

也许你需要Supported interface orientations设置Info.plist

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
于 2021-10-17T22:37:40.517 回答
0

如果您ViewController是孩子ViewController并且您已将其视图添加到 parentViewController的视图中,请执行以下操作:

ViewController在您添加的父级中

self.view.addSubview(childViewController.view)

还添加

self.addChild(childViewController)
于 2021-09-23T08:39:03.147 回答
0

这就是我解决这个问题的方法:

转到项目目标 - 常规 - 部署信息

勾选应用支持的设备方向

您还需要(更改UIInterfaceOrientationMask.all为适当的):

override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get {
        return UIInterfaceOrientationMask.all;
    }
}

对于视图控制器。

于 2018-02-18T10:55:14.997 回答