iOS容器视图不尊重intrinsicContentSize

我想使用容器视图来包含相机预览。 我想让相机居中,保持适当的宽高比。 (这是粉红色的,使其明显的地方在哪里)

显示容器视图的故事板

我被困在试图让相机预览出现在比容器小的尺寸上的第一步。

我有一个相机控制器的视图的UIView子类,并有代码:

- (CGSize)intrinsicContentSize { return CGSizeMake(320, 240); } 

不幸的是,这不是荣幸:

iPad模拟器的结果

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

我该如何做这项工作?

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

粉红色视图将被强制为容器视图的大小,除非您编写一些代码。 无论您是否使用自动布局,情况都是如此。 这只是容器视图在故事板工作中创build的方式。 系统不会问你的粉红色视图的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 

这在我的testing中已经足够了。 (如果子视图dynamic地改变其intrinsicContentSize它不会保持最新。)

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

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

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

将这些sockets连接到故事板中的约束条件。 请注意,这些sockets在CameraContainerView而不是ViewController ,所以不要试图从视图控制器拖拽到约束条件; 那不行。

另外,请确保容器视图不会固定在其超级视图的左侧和右侧(前导和尾随)边缘,也不会固定到其超级视图的顶部和底部。 容器视图的大小仅由其明确的宽度和高度约束来确定是很重要的。

在故事板中设置约束条件并连接sockets之后,可以重写addSubview:以进行自动布局。 您需要closuresembedded式视图上的translatesAutoresizingMaskIntoConstraints

 @implementation CameraContainerView - (void)addSubview:(UIView *)subview { subview.translatesAutoresizingMaskIntoConstraints = NO; [super addSubview:subview]; 

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

  [self removeConstraint:self.widthConstraint]; self.widthConstraint = nil; [self removeConstraint:self.heightConstraint]; self.heightConstraint = nil; 

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

  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 

这工作在我的testing,并应保持最新,如果子视图dynamic更改其intrinsicContentSize ,只要子视图发送自己invalidateIntrinsicContentSize

我发现在界面生成器中的错误。 在它的帮助下,您可以使用intrinsicContentSize添加自定义视图。

1)在界面生成器中的视图添加UIButton。 我设置了centerY和centerX约束。 这个button是你的自定义视图。 在这里输入图像说明

2)将您的自定义视图replace为UIButton的超类:

 @interface CustomView : UIView @end 

 @interface CustomView : UIButton @end 

3)在故事板中设置UIButton类:

在这里输入图像说明

4)返回你的自定义视图的超类:

 @interface CustomView : UIView @end 

5)运行。 我的CustomView在中心屏幕上显示灰色正方形(300х300)。 编译没有错误和警告。

 @implementation CustomView - (void)awakeFromNib { [super awakeFromNib]; self.backgroundColor = [UIColor grayColor]; } - (CGSize)intrinsicContentSize { return CGSizeMake(300, 300); } @end 

结果:

在这里输入图像说明