viewWillTransitionToSize:withTransitionCoordinator: 和 layoutSubviews: 之间的交互

Posted

技术标签:

【中文标题】viewWillTransitionToSize:withTransitionCoordinator: 和 layoutSubviews: 之间的交互【英文标题】:Interaction between viewWillTransitionToSize:withTransitionCoordinator: and layoutSubviews: 【发布时间】:2017-11-14 17:38:05 【问题描述】:

我有一个视图,其中包含我通过覆盖layoutSubviews 管理的子视图。这当然会在创建视图时被调用来进行初始布局。由于应用程序中的状态更改,我根据需要调用setNeedsLayout 来更改布局。这一切都有效。

为了处理旋转,我将覆盖viewWillTransitionToSize:withTransitionCoordinator: 做一些工作来准备旋转(没有可见的;只是内部状态),然后只允许layoutSubviews 按预期使用新大小进行调用。效果很好。

作为此处关于相关主题的讨论的结果,我正在努力将我的子视图的布局和动画移动到对animateAlongsideTransition:completion: 的调用中,该调用协调我的子视图帧的动画与旋转动画的变化。所以在viewWillTransitionToSize:withTransitionCoordinator: 中,我正在计算我所有的新帧,然后调用animateAlongsideTransition:completion: 来为帧更改设置动画。

问题是在我的动画开始之前,layoutSubviews 被调用了 3 次。我已经中断了我自己对setNeedsLayout 的调用,所以我知道这不是我造成的。当layoutSubviews 查看它的边界矩形时,它已经设置为新的(旋转的)宽度和高度。因此,当我的框架设置代码作为旋转转换的一部分被调用时,layoutSubviews 已经正确定位了视图。

我无法删除layoutSubviews,因为我需要它来进行视图的初始配置以及在用户与应用程序交互时发生的各种状态更改。我可以将它重命名为 myLayoutSubviews 并根据需要显式调用它(在 viewDidLoad 和进行状态更改时),但这似乎是一种糟糕的形式。

所以问题是:如何防止layoutSubviews 被调用,或者我如何检测到它是由于轮换而被调用的,并以一种感觉“正确”的方式进行调用?当然有正确的方法可以做到这一点;我就是找不到。

【问题讨论】:

【参考方案1】:

我遇到了类似的问题。对我来说,我必须在初始化程序中使用一个变量initialLayout,我将它设置为false。第一次调用layoutSubviews 时,我将initialLayout 设置为true

obj-c

@implementation CustomViewController 
  BOOL initialLayout;


init 
  self = [super initWithNibName:nil bundle:nil];
  if (self) 
    initialLayout = false;
  
  return self; 


- (void)viewWillLayoutSubviews 
  [super viewWillLayoutSubviews];

  if (initialLayout == false) 
    [self firstLayout];
  


-(void)firstLayout 
  // All my layout code
  initialLayout = true;


 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:
(id<UIViewControllerTransitionCoordinator>)coordinator 
   [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
   // All my layout code

迅速

class CustomViewController : UIViewController 
  var initialLayout: Bool

  init() 
    super.init(nibName: nil, bundle:nil)
    initialLayout = false
  


override viewWillLayoutSubviews() 
   super.viewWillLayoutSubviews()

   if (initialLayout == false) 
     firstLayout()
   


func firstLayout() 
  // All my layout code
  initialLayout = true


override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    super.viewWillTransition(to: size, with: coordinator)
    // All my layout code

【讨论】:

以上是关于viewWillTransitionToSize:withTransitionCoordinator: 和 layoutSubviews: 之间的交互的主要内容,如果未能解决你的问题,请参考以下文章

viewWillTransitionToSize:withTransitionCoordinator: 未调用

为啥 `viewWillTransitionToSize` 中检索 SafeAreaInsets 的逻辑略有错误?

ViewWillTransitionToSize 在 Swift 3 中出现故障?

viewWillTransitionToSize 返回 iPhone 12 pro max 的错误尺寸 [重复]

viewWillTransitionToSize:withTransitionCoordinator: 和 layoutSubviews: 之间的交互

Swift viewWillTransitionToSize 不使用分屏调用