【问题标题】:Stretching an UIImage while preserving the corners在保留角的同时拉伸 UIImage
【发布时间】:2012-02-11 09:11:15
【问题描述】:

我正在尝试在保留边缘的同时拉伸导航箭头图像,以便中间拉伸而末端固定。

这是我要拉伸的图像:

以下 iOS 5 代码允许在调整图像大小时拉伸由 UIEdgeInsets 定义的图像的中心部分。

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

这会产生如下所示的图像(如果图像的框架设置为 70 像素宽):

这实际上是我想要的,但 resizableImageWithCapInsets 仅支持 iOS 5 及更高版本。

在 iOS 5 之前,唯一类似的方法是 stretchableImageWithLeftCapWidth:topCapHeight,但您只能指定顶部和左侧插图,这意味着图像必须具有相同形状的边缘。

是否有与 iOS 5 的 resizableImageWithCapInsets 方法相同的 iOS 4 调整图像大小的方法,或其他方法?

【问题讨论】:

    标签: iphone ios4 ios5 uiimage drawing


    【解决方案1】:

    你的假设是错误的:

    在 iOS 5 之前,唯一类似的方法是 stretchableImageWithLeftCapWidth:topCapHeight,但您只能指定顶部和左侧插入 这意味着图像必须具有相同形状的边缘。

    帽子的计算方法如下 - 我将逐步介绍左边的帽子,但同样的原则也适用于顶帽。

    假设你的图片是 20px 宽。

    • 左帽宽度 - 这是图像左侧无法拉伸的部分。在 stretchableImage 方法中,您为此发送一个值 10。
    • 可拉伸部分 - 假定宽度为 1 个像素,因此它将是“11”列中的像素,因为需要更好的描述
    • 这意味着您的图片的剩余 9 像素有一个隐含的右上限 - 这也不会失真。

    这取自documentation

    leftCapWidth

    结束大写指定在拉伸图像时不应调整大小的图像部分。该技术用于实现按钮和其他可调整大小的基于图像的界面元素。调整带有端盖的按钮的大小时,调整大小仅发生在按钮的中间,端盖之间的区域中。端盖本身保持其原始尺寸和外观。

    此属性指定左端盖的大小。中间(可拉伸)部分假定为 1 个像素宽。因此,右端盖的计算方法是将左端盖和中间部分的大小相加,然后从图像的宽度中减去该值:

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

    【讨论】:

    • 是的,我已经删除了 iOS 5 版本,现在正在使用 stretchableImage,因为我们需要支持运行 iOS4 的设备。谢谢。
    【解决方案2】:
    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
    

    【讨论】:

      【解决方案3】:

      您的示例完全可以使用 stretchableImageWithLeftCapWidth:topCapHeight: 左上限为 15(显然,从阅读您的代码)。这将通过重复中间列来水平拉伸按钮。

      【讨论】:

        【解决方案4】:

        您可以扩展 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
        

        【讨论】:

          【解决方案5】:

          Vicky 的回答的 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)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-03
            • 1970-01-01
            • 1970-01-01
            • 2011-09-19
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多