Растягивание UIImage с сохранением углов - PullRequest
27 голосов
/ 16 января 2012

Я пытаюсь растянуть изображение навигационной стрелки, сохраняя края так, чтобы середина растягивалась, а концы фиксировались.

Вот изображение, которое я пытаюсь растянуть:

enter image description here

Следующий код iOS 5 позволяет при изменении размера изображения растягивать центральные части изображения, определенные UIEdgeInsets.

[[UIImage imageNamed:@"arrow.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(15, 7, 15, 15)];

Это приводит к изображению, которое выглядит следующим образом (если ширина кадра изображения составляет 70 пикселей):

enter image description here

Это на самом деле то, что я хочу, но resizableImageWithCapInsets поддерживается только в iOS 5 и более поздних версиях.

До iOS 5 единственным подобным методом был stretchableImageWithLeftCapWidth: topCapHeight , но вы можете указать только верхнюю и левую вставки, что означает, что у изображения должны быть равные по форме края.

Существует ли в iOS 4 способ изменения размера изображения, аналогичный способу iOS 5 resizableImageWithCapInsets, или другой способ сделать это?

Ответы [ 5 ]

31 голосов
/ 16 января 2012

Ваше предположение здесь неверно:

До iOS 5 единственным подобным методом является stretchableImageWithLeftCapWidth: topCapHeight, но вы можете указать только верхнюю и левую вставки , что означает, что изображение должно иметь одинаковые фасонные края.

Крышки рассчитаны следующим образом - я шагну через левую крышку, но тот же принцип применим к верхней крышке.

Скажите, что ваше изображение имеет ширину 20 пикселей.

  • Ширина левой крышки - это часть на левой стороне изображения, которую нельзя растянуть. В методе stretchableImage для этого вы отправляете значение 10.
  • Растягиваемая часть - предполагается, что она имеет ширину в один пиксель, поэтому это будут пиксели в столбце "11", если не будет лучшего описания
  • Это означает, что подразумевается правая кепка оставшихся 9px вашего изображения - это также не будет искажено.

Это взято из документации

leftCapWidth

Концевые заглушки указывают часть изображения, размер которой не следует изменять при растяжении изображения. Этот метод используется для реализации кнопок и других изменяемых размеров элементов интерфейса на основе изображений. При изменении размера кнопки с торцевыми крышками изменение размера происходит только в середине кнопки, в области между торцевыми крышками. Сами заглушки сохраняют свой первоначальный размер и внешний вид.

Это свойство указывает размер левой заглушки. Предполагается, что средняя (растягиваемая) часть имеет ширину 1 пиксель. Поэтому правая торцевая крышка вычисляется путем сложения размера левой торцевой крышки и средней части, а затем вычитания этого значения из ширины изображения:

rightCapWidth = image.size.width - (image.leftCapWidth + 1);

9 голосов
/ 11 июня 2013
UIImage *image = [UIImage imageNamed:@"img_loginButton.png"];
    UIEdgeInsets edgeInsets;
    edgeInsets.left = 0.0f;
    edgeInsets.top = 0.0f;
    edgeInsets.right = 5.0f; //Assume 5px will be the constant portion in your image
    edgeInsets.bottom = 0.0f;
    image = [image resizableImageWithCapInsets:edgeInsets];
//Use this image as your controls image
5 голосов
/ 16 января 2012

Ваш пример вполне возможен при использовании stretchableImageWithLeftCapWidth:topCapHeight: с левой заглушкой 15 (очевидно, из чтения вашего кода).Это растянет кнопку по горизонтали, повторяя средний столбец.

4 голосов
/ 17 июня 2012

Вы можете расширить UIImage, чтобы разрешить растягивание изображения с пользовательской защитой краев (тем самым растягивая внутреннюю часть изображения, вместо того, чтобы его мозаично):

UIImage + utils.h:

#import <UIKit/UIKit.h>
@interface UIImage(util_extensions)
//extract a portion of an UIImage instance 
-(UIImage *) cutout: (CGRect) coords;
//create a stretchable rendition of an UIImage instance, protecting edges as specified in cornerCaps
-(UIImage *) stretchImageWithCapInsets: (UIEdgeInsets) cornerCaps toSize: (CGSize) size;
@end

UIImage + utils.m:

#import "UIImage+utils.h"
@implementation UIImage(util_extensions)
-(UIImage *) cutout: (CGRect) coords {
    UIGraphicsBeginImageContext(coords.size);
    [self drawAtPoint: CGPointMake(-coords.origin.x, -coords.origin.y)];
    UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return rslt;
}

-(UIImage *) stretchImageWithCapInsets: (UIEdgeInsets) cornerCaps toSize: (CGSize) size { 
    UIGraphicsBeginImageContext(size);

    [[self cutout: CGRectMake(0,0,cornerCaps.left,cornerCaps.top)] drawAtPoint: CGPointMake(0,0)]; //topleft
    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,0,cornerCaps.right,cornerCaps.top)] drawAtPoint: CGPointMake(size.width-cornerCaps.right,0)]; //topright
    [[self cutout: CGRectMake(0,self.size.height-cornerCaps.bottom,cornerCaps.left,cornerCaps.bottom)] drawAtPoint: CGPointMake(0,size.height-cornerCaps.bottom)]; //bottomleft
    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,self.size.height-cornerCaps.bottom,cornerCaps.right,cornerCaps.bottom)] drawAtPoint: CGPointMake(size.width-cornerCaps.right,size.height-cornerCaps.bottom)]; //bottomright

    [[self cutout: CGRectMake(cornerCaps.left,0,self.size.width-cornerCaps.left-cornerCaps.right,cornerCaps.top)]
 drawInRect: CGRectMake(cornerCaps.left,0,size.width-cornerCaps.left-cornerCaps.right,cornerCaps.top)]; //top

    [[self cutout: CGRectMake(0,cornerCaps.top,cornerCaps.left,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(0,cornerCaps.top,cornerCaps.left,size.height-cornerCaps.top-cornerCaps.bottom)]; //left

    [[self cutout: CGRectMake(cornerCaps.left,self.size.height-cornerCaps.bottom,self.size.width-cornerCaps.left-cornerCaps.right,cornerCaps.bottom)]
 drawInRect: CGRectMake(cornerCaps.left,size.height-cornerCaps.bottom,size.width-cornerCaps.left-cornerCaps.right,cornerCaps.bottom)]; //bottom

    [[self cutout: CGRectMake(self.size.width-cornerCaps.right,cornerCaps.top,cornerCaps.right,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(size.width-cornerCaps.right,cornerCaps.top,cornerCaps.right,size.height-cornerCaps.top-cornerCaps.bottom)]; //right

    [[self cutout: CGRectMake(cornerCaps.left,cornerCaps.top,self.size.width-cornerCaps.left-cornerCaps.right,self.size.height-cornerCaps.top-cornerCaps.bottom)]
 drawInRect: CGRectMake(cornerCaps.left,cornerCaps.top,size.width-cornerCaps.left-cornerCaps.right,size.height-cornerCaps.top-cornerCaps.bottom)]; //interior

    UIImage *rslt = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [rslt resizableImageWithCapInsets: cornerCaps];
}

@end
2 голосов
/ 01 марта 2017

Swift 3.0 версия ответа Вики.

var imageInset:UIEdgeInsets = UIEdgeInsets()
        imageInset.left = 10.0
        imageInset.top = 10.0
        imageInset.bottom = 10.0
        imageInset.right = 10.0
        self.myImageView.image = myimage.resizableImage(withCapInsets: imageInset)
...