在iOS中如何进行程序化的等比例缩放?

4

我想使用aspect fit选项将一个视图插入另一个视图中。但由于某些原因,我无法仅仅设置contentMode

您能否提供一种解决方案,通过调整内部CGRect的大小来适应外部CGRect

是的,有很多类似的问题,但没有人提供这样的解决方案。


你可以在其他视图中创建枚举或字符串,并在 viewdidLoad 中设置它。也就是说,在转到另一个控制器时,使用 AspectFit 设置该枚举并在 viewdidLoad 中设置该枚举。 - Mukesh
3个回答

6

我编写了一个函数,可以实现你想要的功能。

它将返回给定的innerRect经过缩放以适应给定的outerRect后的CGRect,同时保持纵横比。 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的宽度过宽,因此将根据其宽度进行缩放。

enter image description here

在这里,红色区域是innerRect,绿色区域是outerRect。它们最初高度相同,但在缩小后(因为宽度是原来的两倍),innerRect现在的高度是outerRect的一半。
在这里,innerRect作为子视图添加到outerRect中。如果您想将它们添加到同一个父视图中,可以将outerRectframe传递到函数中,而不是bounds

4

这里提供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
    }
}

0
    // 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]];

}

我认为这会对你有所帮助。


如果您正在使用CGRect,则不会自动调整到所有屏幕大小,这是一个好的解决方案。 - Muhammad Raheel Mateen
是的,但我需要像我写的那样通过CGRect精确控制。我已经处理了所有的调整大小事件。 - Vyachaslav Gerchicov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接