iOS容器视图不支持intrinsicContentSize

bra*_*ers 8 objective-c uikit ios uistoryboard autolayout

我想使用容器视图来包含相机预览.我希望相机在中间居中并保持适当的宽高比.(它的粉红色使它的框架显而易见)

显示容器视图的故事板

我试图让相机预览显示的尺寸小于容器的第一步.

我有一个用于Camera Controller视图的UIView子类,并且有以下代码:

- (CGSize)intrinsicContentSize
{
  return CGSizeMake(320, 240);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这并不值得尊敬:

iPad模拟器结果

从阅读文档,intrinsicContentSize看起来就像我想要的.最终我也想使用自动布局,但我试图一次解决一件事.

我该如何工作?

rob*_*off 19

自动布局使用该intrinsicContentSize属性.如果您没有使用自动布局,系统将不会询问任何视图intrinsicContentSize.

除非您编写一些代码,否则粉红色视图将被强制为容器视图的大小.无论您是否使用自动布局,都是如此.这就是在故事板工作中创建容器视图的方式.系统不会询问您的粉红色视图intrinsicContentSize.

由于您暗示您没有使用自动布局,因此您可以通过以下方式将容器视图作为intrinsicContentSize其内容视图的一种方式.创建一个UIView被调用的子类,CameraContainerView并将其设置为容器视图的自定义类.覆盖addSubview:这个新类:

@implementation CameraContainerView

- (void)addSubview:(UIView *)subview {
    [super addSubview:subview];
    CGRect frame = self.frame;
    frame.size = subview.intrinsicContentSize;
    self.frame = frame;
}

@end
Run Code Online (Sandbox Code Playgroud)

这在我的测试中就足够了.(如果子视图intrinsicContentSize动态更改,它将不会保持最新状态.)

如果您决定使用自动布局,则需要在容器视图和内容视图之间设置约束,并且需要删除任何冲突的约束.

首先,在故事板中,确保容器视图具有明确的宽度和高度约束.(这些约束将被删除,因此它们的确切大小无关紧要.)CameraContainerView为每个约束提供一个出口:

@interface CameraContainerView ()

@property (nonatomic, strong) IBOutlet NSLayoutConstraint *widthConstraint;
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *heightConstraint;

@end
Run Code Online (Sandbox Code Playgroud)

将这些插座连接到故事板中的约束.请注意,这些插座是打开的CameraContainerView,而不是打开的ViewController,所以不要试图控制 - 从视图控制器拖动到约束; 这是行不通的.

还要确保容器视图不固定到其超视图的左右两边(前端和后端)边缘,并且不会固定到其超视图的顶部和底部.重要的是容器视图的大小只能由其明确的宽度和高度约束来确定.

在故事板中设置约束并连接出口后,您可以重写addSubview:自动布局.您需要关闭translatesAutoresizingMaskIntoConstraints嵌入视图:

@implementation CameraContainerView

- (void)addSubview:(UIView *)subview {
    subview.translatesAutoresizingMaskIntoConstraints = NO;

    [super addSubview:subview];
Run Code Online (Sandbox Code Playgroud)

然后,您需要删除从故事板加载的宽度和高度约束:

    [self removeConstraint:self.widthConstraint];
    self.widthConstraint = nil;
    [self removeConstraint:self.heightConstraint];
    self.heightConstraint = nil;
Run Code Online (Sandbox Code Playgroud)

最后,您可以设置新的约束,将嵌入视图定位在容器视图中,并使容器视图与嵌入视图的大小相匹配:

    NSDictionary *views = NSDictionaryOfVariableBindings(subview);
    [self addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"H:|[subview]|"
        options:0 metrics:nil views:views]];
    [self addConstraints:[NSLayoutConstraint
        constraintsWithVisualFormat:@"V:|[subview]|"
        options:0 metrics:nil views:views]];
}

@end
Run Code Online (Sandbox Code Playgroud)

这在我的测试中起作用,并且如果子视图intrinsicContentSize动态地改变它,它应该保持最新,只要子视图发送自己invalidateIntrinsicContentSize.

  • "明确设置frame.size = subview.intrinsicContentSize"不是"作弊".我在**应用程序没有使用自动布局**的场景中这样做了.阅读我的回答:"既然你暗示你不是*使用自动布局,......" (2认同)