简体   繁体   English

Aspect在iOS中以编程方式适合?

[英]Aspect fit programmatically in iOS?

I want to insert one view into another with aspect fit option. 我想使用宽高比适合选项将一个视图插入另一个视图。 But I can't just set contentMode for some reasons. 但我不能仅仅因为某些原因设置contentMode

Could you provide a solution via resizing of the inner CGRect according to the outer CGRect ? CGRect根据外部CGRect通过调整内部CGRect大小来提供解决方案?

And yes, there are a lot of similar questions but no one provides such solution. 是的,有很多类似的问题,但没有人提供这样的解决方案。

I wrote a function that should achieve what you desire. 我写了一个应该达到你想要的功能。

It will return the CGRect of a given innerRect , after scaling it to fit within a given outerRect , while maintaining aspect ratio. 它将返回CGRect给定的innerRect ,缩放以适合一个给定的内后outerRect ,同时保持高宽比。 The innerRect will be centered within the 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};
}

You can then use this like so: 然后您可以像这样使用它:

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

In this case, the innerRect is too wide for the outerRect , so it will be scaled according to it's width. 在这种情况下, innerRect对于outerRect来说太宽,所以它将根据它的宽度进行缩放。

在此输入图像描述

Here, the red area is the innerRect and the green area is the outerRect . 这里,红色区域是innerRect ,绿色区域是outerRect They both originally had the same height, but after being scaled down (as it was 2x as wide), the innerRect now has half the height of the outerRect . 它们最初都具有相同的高度,但在按比例缩小后(宽度为2 outerRect ), innerRect现在具有outerRect高度的outerRect

Here the innerRect is added as a subview to the outerRect . 这里innerRect作为子视图添加到outerRect If you want to add them to the same superview, you can pass the outerRect 's frame into the function, rather than the bounds . 如果要将它们添加到同一个outerRect ,可以将outerRectframe传递给函数,而不是bounds

Here are CGSize and CGRect extensions for fitting a size within another size and fitting a rect within another rect respectively: 下面是CGSize和CGRect扩展,用于在另一个大小内拟合大小并分别在另一个矩形中拟合rect:

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

}

I think This helps You. 我想这有助于你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM