带边框的UIImage缩放


一个带边框的UIImage如果使用常规的缩放,边框部分将被按照缩放比例拉伸或压缩,有些时候这并不是我们所期望的..比如这个边框是根据图片大小变化的外框。比如下面的类似按钮的不明物体图片:主体为渐变蓝色,边框为外圈白色,灰色底板为背景。Origin post can be found here.

I recently began writing a short example to learn more about the iOS 5 Appearance API and customizing UINavigationBar objects. The goal was to add a custom background, title and text to the navbar. Once I had this working, to keep a consist look across my application, I began tweaking the buttons on the navbar using the same Appearance API.

常见的按钮添加和背景设置如下:

[crayon]
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(80, 130, 160, 44)];
[button setTitle:@”Test Button” forState:UIControlStateNormal];

// Image with without cap insets
UIImage *buttonImage = [UIImage imageNamed:@”blueButton”];

[button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[[self view] addSubview:button];
[/crayon]

所得到的按钮会相当悲剧…

边框,特别是左右边框由于按钮frame过大被惨烈拉伸…

iOS5中提供了一个新的UIImage方法,resizableImageWithCapInsets:,可以将图片转换为以某一偏移值为偏移的可伸缩图像(偏移值内的图像将不被拉伸或压缩)。

用法引述如下:

resizableImageWithCapInsets:

Creates and returns a new image object with the specified cap insets.
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets) capInsets
Parameters
capInsets
The values to use for the cap insets.

Return Value
A new image object with the specified cap insets.

Discussion
You use this method to add cap insets to an image or to change the existing cap insets of an image. In both cases, you get back a new image and the original image remains untouched.

During scaling or resizing of the image, areas covered by a cap are not scaled or resized. Instead, the pixel area not covered by the cap in each direction is tiled, left-to-right and top-to-bottom, to resize the image. This technique is often used to create variable-width buttons, which retain the same rounded corners but whose center region grows or shrinks as needed. For best performance, use a tiled area that is a 1x1 pixel area in size.

输入参数为一个capInsets结构体:

Defines inset distances for views.

typedef struct {
CGFloat top, left, bottom, right;
} UIEdgeInsets;分别表示上左下右四个方向的偏移量。于是把上面按钮的UIImage改为如下形式:
[crayon]
// Image with cap insets
UIImage *buttonImage = [[UIImage imageNamed:@”blueButton”]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 16, 0, 16)];
[/crayon]
可以得到如下按钮:

问题得到解决。

但是值得注意的是该方法需要至少iOS5的运行环境,因此对于需要开发支持iOS5之前的App来说是不可行的。替代方案是stretchableImageWithLeftCapWidth:topCapHeight:,但是在iOS5中,这已经是被Deprecated的方法了,而且该方法只能以1px作为重复铺满拉伸区域,无法做到类似渐变等图片效果,是存在一定局限的。

As I got further into the customization of the buttons, I ran into a method within UIImage that was introduced in iOS 5, resizableImageWithCapInsets. I found myself getting side-tracked from the original idea of navbar look and feel, to understanding how cap insets work. This post delves into what I learned.

Cap Insets with UIButton
As the documentation describes, you use resizableImageWithCapInsets to add cap insets to an image, when the image is resized or scaled, cap areas are not affected. The best way to understand this is through an example.

Let’s assume I want all the buttons on my UI to have a similar look, a gradient with a white border. Below is the image used for the examples in this post (the button is shown on a gray backdrop so you can see the white border):

Depending on the context of where the button appears, its size may vary. The code to create a button with the image and the corresponding output follow:

[crayon]
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(80, 130, 160, 44)];
[button setTitle:@”Test Button” forState:UIControlStateNormal];// Image with without cap insets
UIImage *buttonImage = [UIImage imageNamed:@”blueButton”];[button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[[self view] addSubview:button];
[/crayon]

As you can see, the button is stretched in all directions. Let’s change the code to include cap insets, however, before we do that, let’s look at the signature of the cap insets method:

- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets

Looking on step further, UIEdgeInserts is defined as:

typedef struct {
   CGFloat top, left, bottom, right;
} UIEdgeInsets;
UIEdgeInsets is structure that specifies float values for each cap inset: top, left, bottom and right areas of an image. To apply this to the image for the button, here is all we need to do:
[crayon]
// Image with cap insets
UIImage *buttonImage = [[UIImage imageNamed:@”blueButton”]
resizableImageWithCapInsets:UIEdgeInsetsMake(0, 16, 0, 16)];
[/crayon]
This requests that the left and right 16 pixels of the original image are not scaled or resized when stretching the image to accomodate the button size frame defined above. The end results is as shown below:

Cap Insets with UIBarButtonItem
We can use the same image for a button on a navbar (I’ll show the specifics in the next post on customizing the navbar). Without specifying the cap insets, the button looks as follows:

The code below specifies an image where 12 pixels on the top, left, bottom and right be preserved when stretching/resizing the button:

[crayon]UIImage *backButton = [[UIImage imageNamed:@”blueButton”]
resizableImageWithCapInsets:UIEdgeInsetsMake(12, 12, 12, 12)];
[/crayon]
The output nows looks as follows:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值