问题
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?
回答1:
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
.
回答2:
I found bug in Interface Builder. With its help , you can add custom view with intrinsicContentSize.
1) Add UIButton on View in Interface Builder. I set centerY and centerX constraints. This button is your custom view.
2) Replacement superclass your custom view to UIButton:
@interface CustomView : UIView
@end
to
@interface CustomView : UIButton
@end
3) Set class UIButton in storyboard :
4) Return superclass your custom view:
@interface CustomView : UIView
@end
5) Run. My CustomView show gray square (300х300) on center screen. Compiling without errors and warnings.
@implementation CustomView
- (void)awakeFromNib
{
[super awakeFromNib];
self.backgroundColor = [UIColor grayColor];
}
- (CGSize)intrinsicContentSize
{
return CGSizeMake(300, 300);
}
@end
Result :
来源:https://stackoverflow.com/questions/17376240/ios-container-view-doesnt-honour-intrinsiccontentsize