Aspect fit programmatically in iOS?

跟風遠走 提交于 2019-11-28 10:54:38

问题


I want to insert one view into another with aspect fit option. But I can't just set contentMode for some reasons.

Could you provide a solution via resizing of the inner CGRect according to the outer CGRect?

And yes, there are a lot of similar questions but no one provides such solution.


回答1:


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. The innerRect will be centered within the 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.

Here, the red area is the innerRect and the green area is the 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.

Here the innerRect is added as a subview to the 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.




回答2:


Here are CGSize and CGRect extensions for fitting a size within another size and fitting a rect within another rect respectively:

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
    }
}



回答3:


    // 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.



来源:https://stackoverflow.com/questions/35507331/aspect-fit-programmatically-in-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!