自动布局和UIPopoverController

8

我创建了一个面板,并在其中添加了一些子视图,使用NSLayoutConstraint来实现定位。

然后,我会将它显示在一个UIPopoverController中。在设置之前,我会调用[UIView layoutIfNeeded]命令来强制其自适应大小(整体大小基于其中的图像大小,可能是不同的尺寸)。

PhotoDisplayPanel *panel = [[PhotoDisplayPanel alloc] initWithPhoto:cell.photo isAddPhoto:cell.isAddPhoto];

DLog(@"BEFORE | panel.frame: %@", panel);

[self.view addSubview:panel];

DLog(@"MIDDLE | panel.frame: %@", panel);

[panel layoutIfNeeded];

DLog(@"AFTER | panel.frame: %@", panel);

日志:

DEBUG | -[LoginViewController viewDidLoad] | BEFORE | panel.frame: <PhotoDisplayPanel: 0x7878a3f0; frame = (0 0; 0 0); layer = <CALayer: 0x7878a7e0>>
DEBUG | -[LoginViewController viewDidLoad] | MIDDLE | panel.frame: <PhotoDisplayPanel: 0x7878a3f0; frame = (0 0; 0 0); layer = <CALayer: 0x7878a7e0>>
DEBUG | -[LoginViewController viewDidLoad] | AFTER | panel.frame: <PhotoDisplayPanel: 0x7878a3f0; frame = (-358 -245; 578 289); layer = <CALayer: 0x7878a7e0>>

以前,我会在将一个面板添加到视图之前添加[panel layoutIfNeeded]调用。 这样做效果很好。 但是在iOS 8.1中,他们改变了 layoutIfNeeded的工作方式,如果你在将我的面板添加到视图之前调用它,它就会出现问题并开始打破约束以使其正常工作。

我的问题是处理UIPopoverController时,由于我无法调用layoutIfNeeded,所以我的面板没有大小,因此它使用弹出窗口的默认大小:

enter image description here

而实际上面板应该如下图所示:

enter image description here

我创建了UIPopoverController,将面板作为其视图设置,然后设置preferedContentSize属性为面板的大小:

UIViewController *viewController = [[UIViewController alloc] init];
viewController.view = self.currentPanel;
viewController.preferredContentSize = CGSizeMake(self.currentPanel.frame.size.width, self.currentPanel.frame.size.height + 00);

由于面板没有被调整大小,因此它的大小为(0,0)。

我的问题是如何根据约束条件强制调整面板大小?

2个回答

17
解决方法是根据您的约束条件计算preferredContentSize。 注意:您的约束条件必须固定(左/上/右/下)到视图控制器视图上,以便能够计算视图的总宽度/高度。
要实现此目的,在viewWillAppear中添加以下代码行:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

CGSize resultSize = [self.view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
self.preferredContentSize = resultSize;
}

2
这应该被标记为答案。我测试过了,它运行得很好。 - Sipke Schoorstra
在Swift中,这是 self.preferredContentSize = self.view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) - Nikolay Suvandzhiev
请注意,当@Tanguy说“您的约束必须固定在视图控制器视图上”时,请确保您最宽的UI元素具有相对于视图的尾部锚点约束,而您最底部的UI元素具有相对于视图的底部锚点约束,例如:widestItem.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16)view.bottomAnchor.constraint(equalTo: bottomMostItem.bottomAnchor, constant: 16) - JJJSchmidt

0

Tanguy G. 的工作答案的 Swift 版本 4/5:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let resultSize = view.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    self.preferredContentSize = resultSize
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接