iOS:方向改变后弹回视图控制器时约束中断
iOS: Constraints break when popping back to view controller after orientation is changed
嗨学生学习swift这里。在 iPad 上,我一直在构建一个自定义分段控件应用程序,在纵向模式下,分段控件位于顶部,在横向模式下,控件位于左侧。分段控件是通过在 UIView 中嵌入一个 collectionView 来实现的。这只是帮助我将 datasource/delegate 方法与 viewController 方法分开。内容由标准的嵌套 collectionView 显示。像这样:
我已经设法在没有任何警告或错误的情况下处理此视图控制器内的旋转。我启动了纵向和横向的两个约束数组,并根据需要 deactivate/activate 在 viewWillTransitionToSize
中。问题发生在:
新的视图控制器被推到这个控制器上 -> 设备旋转 -> 弹回到这个控制器。
在新的视图控制器上旋转到纵向并弹出会导致“UICollectionViewFLowLayout 未定义”错误。旋转到横向不太严重,它会导致内容集合视图的大小错误。像这样:
下面是我对 viewWillTransitionToSize
的实现。谢谢!我会很感激任何想法。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
segmentedControl.collectionView.collectionViewLayout.invalidateLayout()
segmentedControl.collectionView.reloadData()
contentScroll.collectionViewLayout.invalidateLayout()
contentScroll.reloadData()
super.viewWillTransition(to: size, with: coordinator)
NSLayoutConstraint.deactivate(p) //deactivate constraints for portrait and landscape
NSLayoutConstraint.deactivate(l)
if isPortrait {
if let layout = segmentedControl.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
NSLayoutConstraint.activate(p)
DispatchQueue.main.async { //scrolling content and segmentedControl to their correct places
self.jumpContentViewToIndex(tabIndex: self.targetIndex, animated: false)
self.segmentedControl.scrollAndUpdateIndex(to: self.targetIndex)
}
} else {
if let layout = segmentedControl.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .vertical
}
NSLayoutConstraint.activate(l)
DispatchQueue.main.async { //scrolling content and segmentedControl to their correct places
self.contentScroll.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
self.segmentedControl.scrollAndUpdateIndex(to: self.targetIndex)
}
}
}
在浏览了很多 Whosebug 链接后,我找到了一个有用的答案 here and 。我的问题是因为位于导航堆栈中间的视图控制器在下一次布局传递之前不会重新计算其布局。您可以通过在旋转期间调用 layoutIfNeeded()
来强制更新布局,或者我所做的是将所有旋转逻辑移动到 viewDidLayoutSubviews()
并在 viewWillTransition:tosize
中设置一个标志以检查您是否需要执行你的旋转逻辑。
嗨学生学习swift这里。在 iPad 上,我一直在构建一个自定义分段控件应用程序,在纵向模式下,分段控件位于顶部,在横向模式下,控件位于左侧。分段控件是通过在 UIView 中嵌入一个 collectionView 来实现的。这只是帮助我将 datasource/delegate 方法与 viewController 方法分开。内容由标准的嵌套 collectionView 显示。像这样:
我已经设法在没有任何警告或错误的情况下处理此视图控制器内的旋转。我启动了纵向和横向的两个约束数组,并根据需要 deactivate/activate 在 viewWillTransitionToSize
中。问题发生在:
新的视图控制器被推到这个控制器上 -> 设备旋转 -> 弹回到这个控制器。
在新的视图控制器上旋转到纵向并弹出会导致“UICollectionViewFLowLayout 未定义”错误。旋转到横向不太严重,它会导致内容集合视图的大小错误。像这样:
下面是我对 viewWillTransitionToSize
的实现。谢谢!我会很感激任何想法。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
segmentedControl.collectionView.collectionViewLayout.invalidateLayout()
segmentedControl.collectionView.reloadData()
contentScroll.collectionViewLayout.invalidateLayout()
contentScroll.reloadData()
super.viewWillTransition(to: size, with: coordinator)
NSLayoutConstraint.deactivate(p) //deactivate constraints for portrait and landscape
NSLayoutConstraint.deactivate(l)
if isPortrait {
if let layout = segmentedControl.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
}
NSLayoutConstraint.activate(p)
DispatchQueue.main.async { //scrolling content and segmentedControl to their correct places
self.jumpContentViewToIndex(tabIndex: self.targetIndex, animated: false)
self.segmentedControl.scrollAndUpdateIndex(to: self.targetIndex)
}
} else {
if let layout = segmentedControl.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .vertical
}
NSLayoutConstraint.activate(l)
DispatchQueue.main.async { //scrolling content and segmentedControl to their correct places
self.contentScroll.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
self.segmentedControl.scrollAndUpdateIndex(to: self.targetIndex)
}
}
}
在浏览了很多 Whosebug 链接后,我找到了一个有用的答案 here and layoutIfNeeded()
来强制更新布局,或者我所做的是将所有旋转逻辑移动到 viewDidLayoutSubviews()
并在 viewWillTransition:tosize
中设置一个标志以检查您是否需要执行你的旋转逻辑。