UIImage Aspect Fit при использовании drawInRect? - PullRequest
26 голосов
/ 14 января 2012

UIView обеспечивает режим содержимого «подгонка аспекта».Тем не менее, я имею подклассы UIView и хотел бы нарисовать UIImage, используя drawInRect с подгонкой аспекта.Могу ли я получить доступ к этой функции без использования UIImageView?

Ответы [ 6 ]

39 голосов
/ 14 января 2012

Математика для этого немного сложновата, но, к счастью, вот решение, которое я подготовил ранее:

- (UIImage *)imageScaledToSize:(CGSize)size
{
    //create drawing context
    UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);

    //draw
    [self drawInRect:CGRectMake(0.0f, 0.0f, size.width, size.height)];

    //capture resultant image
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return image;
}

- (UIImage *)imageScaledToFitSize:(CGSize)size
{
    //calculate rect
    CGFloat aspect = self.size.width / self.size.height;
    if (size.width / aspect <= size.height)
    {
        return [self imageScaledToSize:CGSizeMake(size.width, size.width / aspect)];
    }
    else
    {
        return [self imageScaledToSize:CGSizeMake(size.height * aspect, size.height)];
    }
}

Первая функция эквивалентна «масштабированию для заполнения», вторая (которая вызываетво-первых) эквивалентно «аспекту соответствия».Эти методы были написаны как категория на UIImage, поэтому для использования их в другом классе вам нужно настроить их, передав изображение в качестве второго параметра (или просто создать категорию на UIImage, как я).

26 голосов
/ 19 августа 2015

Вы должны нарисовать в прямоугольнике, предоставленном

Swift:

func AVMakeRect(aspectRatio: CGSize, insideRect boundingRect: CGRect) -> CGRect

Objective-C:

CGRect AVMakeRectWithAspectRatioInsideRect(CGSize aspectRatio, CGRect boundingRect);

См. Документ

Соотношение сторон сохраняется, а рисунок центрируется.

Работает абсолютно во всех случаях.

11 голосов
/ 10 апреля 2013

вот решение

CGSize imageSize = yourImage.size;
CGSize viewSize = CGSizeMake(450, 340); // size in which you want to draw

float hfactor = imageSize.width / viewSize.width;
float vfactor = imageSize.height / viewSize.height;

float factor = fmax(hfactor, vfactor);

// Divide the size by the greater of the vertical or horizontal shrinkage factor
float newWidth = imageSize.width / factor;
float newHeight = imageSize.height / factor;

CGRect newRect = CGRectMake(xOffset,yOffset, newWidth, newHeight);
[image drawInRect:newRect];

- вежливость https://stackoverflow.com/a/1703210

другая альтернатива для подгонки аспекта

-(CGSize ) getImageSize :(CGSize )imgViewSize andActualImageSize:(CGSize )actualImageSize {

     // imgViewSize = size of view in which image is to be drawn
     // actualImageSize = size of image which is to be drawn

     CGSize drawImageSize;

     if (actualImageSize.height > actualImageSize.width) {

        drawImageSize.height = imgViewSize.height;
        drawImageSize.width = actualImageSize.width/actualImageSize.height * imgViewSize.height;

     }else {

        drawImageSize.width = imgViewSize.width;
        drawImageSize.height = imgViewSize.width * actualImageSize.height /  actualImageSize.width;
     }
     return drawImageSize;
}

Код для Swift 3.0:

func getAspectFitFrame(sizeImgView:CGSize, sizeImage:CGSize) -> CGRect{

    let imageSize:CGSize  = sizeImage
    let viewSize:CGSize = sizeImgView

    let hfactor : CGFloat = imageSize.width/viewSize.width
    let vfactor : CGFloat = imageSize.height/viewSize.height

    let factor : CGFloat = max(hfactor, vfactor)

    // Divide the size by the greater of the vertical or horizontal shrinkage factor
    let newWidth : CGFloat = imageSize.width / factor
    let newHeight : CGFloat = imageSize.height / factor

    var x:CGFloat = 0.0
    var y:CGFloat = 0.0
    if newWidth > newHeight{
        y = (sizeImgView.height - newHeight)/2
    }
    if newHeight > newWidth{
        x = (sizeImgView.width - newWidth)/2
    }
    let newRect:CGRect = CGRect(x: x, y: y, width: newWidth, height: newHeight)

    return newRect

}
2 голосов
/ 20 июня 2017

Вот вспомогательное расширение CGSize, которое может оказаться полезным:

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

Тогда в реализации -drawInRect: можно сделать следующее:

let imageSizeThatFitsViewBounds = self.image.size.sizeThatFitsSize(self.bounds.size)
let imageRectX = (self.bounds.size.width - imageSizeThatFitsViewBounds.width) / 2
let imageRectY = (self.bounds.size.height - imageSizeThatFitsViewBounds.height) / 2
let imageRect = CGRect(origin: CGPoint(x: imageRectX, y: imageRectY), size: imageSizeThatFitsViewBounds)
2 голосов
/ 03 ноября 2016

это может вам помочь, попробуйте

UIImage *logoImage = [UIImage imageNamed:@"logo.png"];

float newHeight = ((logoImage.size.height / logoImage.size.width) * 100.0);
CGRect newLogoImageRect = CGRectMake(0, 0, 80.0, newHeight);
[logoImage drawInRect:newLogoImageRect];

укажите максимальную высоту вместо 100,0 и максимальную ширину вместо 80,0

1 голос
/ 30 июля 2013

Следующее позволит вам определить размер для рисования. Вы указываете соотношение сторон и ограничивающий размер для встраивания.

CGSizeAspectFit & CGSizeAspectFill

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...