I want to use a Container View to contain a camera preview. I want the camera to centered in the middle and maintain it's proper aspect ratio. (it's pink to make it obvious where its frame is)
I'm stuck on the first step of trying to get the camera preview to appear at a size that's smaller than the container.
I have a UIView subclass for the Camera Controller's view, and have the code:
- (CGSize)intrinsicContentSize
{
return CGSizeMake(320, 240);
}
Unfortunately this isn't honoured:
From reading the docs, intrinsicContentSize
looks like it's what I want. Eventually I want to use Auto Layout as well, but I'm trying to solve one thing at a time.
How do I make this work?
Auto layout uses the intrinsicContentSize
property. If you're not using auto layout, the system will not ask any view for its intrinsicContentSize
.
The pink view will be forced to the size of the container view unless you write some code. This is true whether you are using auto layout or not. This is just the way container views created in a storyboard work. The system will not ask your pink view for its intrinsicContentSize
.
Since you imply that you're not using auto layout, here's one way you can make the container view be the intrinsicContentSize
of its content view. Make a subclass of UIView
called CameraContainerView
and set this as the custom class of the container view. Override addSubview:
in this new class:
@implementation CameraContainerView
- (void)addSubview:(UIView *)subview {
[super addSubview:subview];
CGRect frame = self.frame;
frame.size = subview.intrinsicContentSize;
self.frame = frame;
}
@end
That is sufficient in my testing. (It won't stay up to date if the subview changes its intrinsicContentSize
dynamically.)
If you decide to use auto layout, you need to set up constraints between the container view and the content view, and you need to remove any conflicting constraints.
First, in your storyboard, make sure the container view has explicit width and height constraints. (These constraints will be deleted so their exact sizes don't matter.) Give CameraContainerView
an outlet for each of these constraints:
@interface CameraContainerView ()
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *widthConstraint;
@property (nonatomic, strong) IBOutlet NSLayoutConstraint *heightConstraint;
@end
Connect these outlets to the constraints in the storyboard. Note that these outlets are on CameraContainerView
, not on ViewController
, so don't try to control-drag from the view controller to the constraints; that won't work.
Also make sure that the container view isn't pinned to both the left and right (leading and trailing) edges of its superview, and that it isn't pinned to both the top and bottom of its superview. It's important that the container view's size be determined only by its explicit width and height constraints.
After you've set up the constraints in the storyboard and hooked up the outlets, you can rewrite addSubview:
for auto layout. You'll need to turn off translatesAutoresizingMaskIntoConstraints
on the embedded view:
@implementation CameraContainerView
- (void)addSubview:(UIView *)subview {
subview.translatesAutoresizingMaskIntoConstraints = NO;
[super addSubview:subview];
Then you need to remove the width and height constraints that were loaded from the storyboard:
[self removeConstraint:self.widthConstraint];
self.widthConstraint = nil;
[self removeConstraint:self.heightConstraint];
self.heightConstraint = nil;
Finally you can set up new constraints that position the embedded view in the container view and make the container view match the size of the embedded view:
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
That worked in my testing, and should stay up to date if the subview changes its intrinsicContentSize
dynamically, as long as the subview sends itself invalidateIntrinsicContentSize
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With