如何在不拉伸中心的情况下拉伸UIImageView?

时间:2013-03-15 07:58:19

标签: iphone ios

enter image description here

我想拉伸上图所示的左右两侧,并保持中间箭头不拉伸。我怎么能这样做?

6 个答案:

答案 0 :(得分:7)

使用Photoshop或其他图像编辑工具将图像分成两部分:边缘和中心。边缘图像可以是一个像素宽并用于左右边缘;然而,中心有很多像素宽,可以捕捉到箭头。然后,您可以将三个UIImageView实例放在一起:左边缘,中间边缘和右边缘。左右边缘的大小调整为所需宽度,而中心保持原始尺寸。

答案 1 :(得分:7)

如果您不喜欢麻烦的Photoshop,并且如果图像没有通过动态调整大小,您可以在UIImage上使用我的类别方法。

名为“17maA.png”的示例图像宽度为124像素。因此,您可以轻松地创建一个300 px宽的版本:

UIImage *image = [UIImage imageNamed:@"17maA"];
UIImage *newImage = [image pbResizedImageWithWidth:300 andTiledAreaFrom:10 to:20 andFrom:124-20 to:124-10];

这是类别方法:

- (UIImage *)pbResizedImageWithWidth:(CGFloat)newWidth andTiledAreaFrom:(CGFloat)from1 to:(CGFloat)to1 andFrom:(CGFloat)from2 to:(CGFloat)to2  {
    NSAssert(self.size.width < newWidth, @"Cannot scale NewWidth %f > self.size.width %f", newWidth, self.size.width);

    CGFloat originalWidth = self.size.width;
    CGFloat tiledAreaWidth = (newWidth - originalWidth)/2;

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(originalWidth + tiledAreaWidth, self.size.height), NO, self.scale);

    UIImage *firstResizable = [self resizableImageWithCapInsets:UIEdgeInsetsMake(0, from1, 0, originalWidth - to1) resizingMode:UIImageResizingModeTile];
    [firstResizable drawInRect:CGRectMake(0, 0, originalWidth + tiledAreaWidth, self.size.height)];

    UIImage *leftPart = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(newWidth, self.size.height), NO, self.scale);

    UIImage *secondResizable = [leftPart resizableImageWithCapInsets:UIEdgeInsetsMake(0, from2 + tiledAreaWidth, 0, originalWidth - to2) resizingMode:UIImageResizingModeTile];
    [secondResizable drawInRect:CGRectMake(0, 0, newWidth, self.size.height)];

    UIImage *fullImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return fullImage;
}

答案 2 :(得分:3)

Klaas的答案对我很有帮助,在Swift 3.0中也是如此:

static func stretchImageSides(image: UIImage, newWidth: CGFloat) -> UIImage? {
    guard image.size.width < newWidth else {
        return image
    }

    let originalWidth = image.size.width
    let tiledAreaWidth = ceil(newWidth - originalWidth) / 2.0;

    UIGraphicsBeginImageContextWithOptions(CGSize(width: originalWidth + tiledAreaWidth, height: image.size.height),
                                           false, image.scale)

    let firstResizable = image.resizableImage(withCapInsets: UIEdgeInsets(top: 0,
                                                                          left: 0,
                                                                          bottom: 0,
                                                                          right: originalWidth - 3),
                                              resizingMode: .stretch)
    firstResizable.draw(in: CGRect(x: 0, y: 0, width: originalWidth + tiledAreaWidth, height: image.size.height))

    let leftPart = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    UIGraphicsBeginImageContextWithOptions(CGSize(width: newWidth, height: image.size.height),
                                           false, image.scale)

    let secondResizable = leftPart?.resizableImage(withCapInsets: UIEdgeInsets(top: 0,
                                                                              left: tiledAreaWidth + originalWidth - 3,
                                                                              bottom: 0,
                                                                              right: 0),
                                              resizingMode: .stretch)
    secondResizable?.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: image.size.height))

    let fullImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return fullImage
}
  • 您只需要提供一个具有所需新宽度的图像,它就会为您进行水平拉伸。

答案 3 :(得分:1)

(没有多大帮助,但有相反的支持:拉伸图像的中心并保持边缘部分的大小相同:请参阅Stretching an UIImage while preserving the corners。)

要制作自己的解决方案,您可以创建一个包含三个部分的组件:左图像,中央图像,右图像。然后通过确保中心部分保持相同的宽度,同时左/右组件(图像)拉伸来处理组件的尺寸更改。

替代策略:创建一个两个图像堆叠在一起的组件。较低的图像是扁平条位(没有三角形)并且水平拉伸以填充可用空间。上图是三角形中心部分,以可用空间为中心。这会产生你正在寻找的效果。

此外,有一个应用程序(不是免费的!)可以帮助您创建具有可伸缩特性的漂亮组件:PaintCode

答案 4 :(得分:0)

基于@Arashk的答案,它是一个带有UIImage参数的Swift size扩展名。

被拉伸的图像的中心仍然居中。

extension UIImage {

  func strechedImageSides(newSize: CGSize) -> UIImage? {
    guard size.width < newSize.width || size.height < newSize.height else {
      return self
    }

    let originalWidth = size.width
    let originalHeight = size.height

    let tiledAreaWidth  = ceil(newSize.width  - originalWidth)  / 2.0
    let tiledAreaHeight = ceil(newSize.height - originalHeight) / 2.0

    UIGraphicsBeginImageContextWithOptions(CGSize(width: originalWidth + tiledAreaWidth,
                                                  height: originalHeight + tiledAreaHeight),
                                           false,
                                           scale)

    let bottomRightResizable = resizableImage(withCapInsets: UIEdgeInsets(top: 0,
                                                                                left: 0,
                                                                                bottom: originalHeight - 1,
                                                                                right: originalWidth - 1),
                                                    resizingMode: .stretch)
    bottomRightResizable.draw(in: CGRect(x: 0,
                                         y: 0,
                                         width: originalWidth + tiledAreaWidth,
                                         height: originalHeight + tiledAreaHeight))

    let topLefthPart = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    UIGraphicsBeginImageContextWithOptions(newSize,
                                           false,
                                           scale)

    let topLeftResizable = topLefthPart?.resizableImage(withCapInsets: UIEdgeInsets(top: tiledAreaHeight + originalHeight - 1,
                                                                                    left: tiledAreaWidth + originalWidth - 1,
                                                                                    bottom: 0,
                                                                                    right: 0),
                                                        resizingMode: .stretch)

    topLeftResizable?.draw(in: CGRect(origin: .zero, size: newSize))

    let fullImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return fullImage
  }
}

答案 5 :(得分:-2)

我们可以使用以下代码拉伸图像: - 在这里我们需要箭头标记部分必须是相同的大小,所以我们拉伸箭头标记开始下方的中间部分(假设它将是2 px)

UIImage *image = [UIImage imageNamed:@"img_loginButton.png"];
    UIEdgeInsets edgeInsets;
    edgeInsets.left = 0.0f;
    edgeInsets.top = 2.0f;
    edgeInsets.right = 0.0f;
    edgeInsets.bottom = 0.0f;
    image = [image resizableImageWithCapInsets:edgeInsets];
//Use this image as your controls image