Аспект вписывается программно в iOS?
Я хочу вставить один вид в другой с опцией подгонки. Но я не могу просто установить contentMode
по некоторым причинам.
Не могли бы вы предоставить решение путем изменения размера внутреннего CGRect
в соответствии с внешним CGRect
?
И да, есть много подобных вопросов, но никто не предлагает такое решение.
3 ответа
Я написал функцию, которая должна достичь того, что вы хотите.
Это вернет CGRect
данного innerRect
после масштабирования, чтобы соответствовать outerRect
, сохраняя при этом пропорции. innerRect
будет сосредоточено в пределах outerRect
,
static inline CGRect aspectFitRect(CGRect outerRect, CGRect innerRect) {
// the width and height ratios of the rects
CGFloat wRatio = outerRect.size.width/innerRect.size.width;
CGFloat hRatio = outerRect.size.height/innerRect.size.height;
// calculate scaling ratio based on the smallest ratio.
CGFloat ratio = (wRatio < hRatio)? wRatio:hRatio;
// The x-offset of the inner rect as it gets centered
CGFloat xOffset = (outerRect.size.width-(innerRect.size.width*ratio))*0.5;
// The y-offset of the inner rect as it gets centered
CGFloat yOffset = (outerRect.size.height-(innerRect.size.height*ratio))*0.5;
// aspect fitted origin and size
CGPoint innerRectOrigin = {xOffset+outerRect.origin.x, yOffset+outerRect.origin.y};
CGSize innerRectSize = {innerRect.size.width*ratio, innerRect.size.height*ratio};
return (CGRect){innerRectOrigin, innerRectSize};
}
Затем вы можете использовать это так:
// outer rect
CGRect outerRect = CGRectMake(0, 100, self.view.bounds.size.width, 500);
// outer rect's view
UIView* v = [[UIView alloc] initWithFrame:outerRect];
v.backgroundColor = [UIColor greenColor];
[self.view addSubview:v];
// inner rect
CGRect innerRect = CGRectMake(0, 0, self.view.bounds.size.width*2, 500);
CGRect scaledInnerRect = aspectFitRect(v.bounds, innerRect);
// inner rect's view
UIView* v1 = [[UIView alloc] initWithFrame:scaledInnerRect];
v1.backgroundColor = [UIColor redColor];
[v addSubview:v1];
В этом случае innerRect
слишком широк для outerRect
, поэтому он будет масштабироваться в соответствии с его шириной.
Здесь красная область innerRect
и зеленая зона является outerRect
, Первоначально они оба имели одинаковую высоту, но после уменьшения (так как ширина была в 2 раза), innerRect
теперь имеет половину высоты outerRect
,
Здесь innerRect
добавляется как подпредставление к outerRect
, Если вы хотите добавить их в одно и то же суперпредставление, вы можете передать outerRect
"s frame
в функцию, а не bounds
,
Вот расширения CGSize и CGRect для подгонки размера в пределах другого размера и подгонки прямоугольника в другом прямоугольнике соответственно:
extension CGSize
{
func sizeThatFitsSize(_ aSize: CGSize) -> CGSize
{
let width = min(self.width * aSize.height / self.height, aSize.width)
return CGSize(width: width, height: self.height * width / self.width)
}
}
extension CGRect
{
func rectThatFitsRect(_ aRect:CGRect) -> CGRect
{
let sizeThatFits = self.size.sizeThatFitsSize(aRect.size)
let xPos = (aRect.size.width - sizeThatFits.width) / 2
let yPos = (aRect.size.height - sizeThatFits.height) / 2
let ret = CGRect(x: xPos, y: yPos, width: sizeThatFits.width, height: sizeThatFits.height)
return ret
}
}
// Your First View
UIView *firstView = self;
// Your second View
UIView *secondView = [[UIView alloc] initWithFrame:CGRectZero]; change
newSubview.translatesAutoresizingMaskIntoConstraints = NO;
[containerView addSubview:newSubview];
// Top Constraint
[firstView addConstraint:[NSLayoutConstraint constraintWithItem:secondView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:firstView
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0.0]];
// Leading Constraint
[firstView addConstraint:[NSLayoutConstraint constraintWithItem:secondView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:firstView
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0.0]];
// Bottom Constraint
[firstView addConstraint:[NSLayoutConstraint constraintWithItem:secondView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:firstView
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:0.0]];
// Trailing Constraint
[firstView addConstraint:[NSLayoutConstraint constraintWithItem:secondView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:firstView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0.0]];
}
Я думаю, что это помогает вам.