iOS開發中我們會遇到漸變的背景,內容可變的流式標簽,聊天氣泡(QQ聊天氣泡),由於內容是可變的,寬度和高度同樣可變,這樣就是導致每次出現的尺寸與之前不一樣。如果是需要設置的比較的多,估計美工會煩死,同樣也會額外增加的內存開銷,所以這個知道一點圖片拉伸的技巧會師我們的能使我們APP更加高效,代碼更加簡潔,事半功倍~從設置的角度來有四種方法可以實現~
Assets設置
首先我們有一個不規則的氣泡按鈕,大小是35*30,Slices選中水平和垂直方向的距離,寬高設置為1

設置完成之,我們設置Button的背景圖片看下加載效果:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(80, 100, 100, 40)];
UIImage *buttonImage = [UIImage imageNamed:@"Question"];
[button setTitle:@"默認" forState:UIControlStateNormal];
[button addTarget:self action:@selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
[button setBackgroundImage:buttonImage forState:UIControlStateNormal];
[self.view addSubview:button];
模擬器加載效果:

第一個圖片是我們需要加載效果,如果我們將Slices設置為None,我們看到的效果是這樣的:

看到這里是不是感覺有點興趣了,為什么設置了上面的選項就可以出現平鋪的效果,稍微思考一下,我們在下面的一種方式中將找到答案~
iOS5之前的設置
上圖的第二個按鈕是我們通過代碼設置,不是在Assets中設置,我們先來看一下實現代碼:
//35*30
UIButton *nextButton = [[UIButton alloc] initWithFrame:CGRectMake(80, 180, 100, 40)];
[nextButton setTitle:@"iOS5之前" forState:UIControlStateNormal];
nextButton.layer.borderColor=[[UIColor redColor] CGColor];
nextButton.layer.borderWidth=1.0f;
UIImage *image = [UIImage imageNamed:@"Question"];
// 設置左邊端蓋寬度 rightCap=width - leftCapWidth - 1
NSInteger leftCapWidth = image.size.width * 0.5;
// 設置上邊端蓋高度 bottom=height - topCapWidth - 1
NSInteger topCapHeight = image.size.height * 0.5;
UIImage *newImage = [image stretchableImageWithLeftCapWidth:leftCapWidth topCapHeight:topCapHeight];
[nextButton setBackgroundImage:newImage forState:UIControlStateNormal];
[self.view addSubview:nextButton];
新建圖片,設置按鈕的背景圖片,與一般設置沒有什么區別,不過多了stretchableImageWithLeftCapWidth:方法,我們看一下API說明:
@interface UIImage(UIImageDeprecated) // use resizableImageWithCapInsets: and capInsets. - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight __TVOS_PROHIBITED; @property(nonatomic,readonly) NSInteger leftCapWidth __TVOS_PROHIBITED; // default is 0. if non-zero, horiz. stretchable. right cap is calculated as width - leftCapWidth - 1 @property(nonatomic,readonly) NSInteger topCapHeight __TVOS_PROHIBITED; // default is 0. if non-zero, vert. stretchable. bottom cap is calculated as height - topCapWidth - 1 @end
我們需要設置拉伸區域具體圖片的上方和左邊的距離:
strechWidth=width-leftCapWidth-(width-leftCapWidth-1)=1
strechHeight=height-rightCaopWidth-(height - topCapWidth - 1)=1
所以我們拉伸的區域是1*1,關於上面的leftCapWidth有人可能心里有疑問,為什么leftCapWidth = image.size.width * 0.5,為什么是0.5?自己最開始隨便設置一個距離結果圖片丑的要死,比如說我們左邊設置0.2,上邊設置為0.8,我們看到的效果是這樣的:

這是極端情況,默認的情況下不管圖片是如何的規則,中間的1*1區域是正方形,如果按照上面設置,我們會發現,上下左右四個點組成的圖片是極其不規則,因此建議設置在中間,不過有的是有偏離一些也沒有太多問題,比如說0.4,0.6對於比例設置大家如果有興趣的可以之后下載代碼,自行研究~
iOS5設置
stretchableImageWithLeftCapWidth在iOS5之后已經廢棄,我們可以通過resizableImageWithCapInsets來設置上下左右邊距~
resizableImageWithCapInsets與之前的方法一樣,同樣是通過重置產生新的圖片:
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); // create a resizable version of this image. the interior is tiled when drawn.
UIEdgeInsets基本上UI中比較常見:
typedef struct UIEdgeInsets {
CGFloat top, left, bottom, right; // specify amount to inset (positive) for each of the edges. values can be negative to 'outset'
} UIEdgeInsets;
圖片效果參考模擬器的第三個按鈕,設置代碼如下:
UIImage *image = [UIImage imageNamed:@"Question"];
UIButton *resizableButton=[[UIButton alloc]initWithFrame:CGRectMake(80, 250, 100, 40)];
[resizableButton setTitle:@"iOS5" forState:UIControlStateNormal];
// 設置端蓋的值
CGFloat top = image.size.height * 0.5;
CGFloat left = image.size.width * 0.5;
CGFloat bottom = image.size.height * 0.5;
CGFloat right = image.size.width * 0.5;
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(top, left, bottom, right);
//拉伸圖片
UIImage *edgeImage = [image resizableImageWithCapInsets:edgeInsets];
//背景圖片
[resizableButton setBackgroundImage:edgeImage forState:UIControlStateNormal];
[self.view addSubview:resizableButton];
iOS6設置
iOS6的設置方法和iOS5差不多,多了一個參數UIImageResizingMode:
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0); // the interior is resized according to the resizingMode
UIImageResizingMode說明:
typedef NS_ENUM(NSInteger, UIImageResizingMode) {
UIImageResizingModeTile,平鋪模式,通過重復顯示UIEdgeInsets指定的矩形區域來填充圖片
UIImageResizingModeStretch, };拉伸模式,通過拉伸UIEdgeInsets指定的矩形區域來填充圖片
實際效果參考上圖中的最后一個按鈕:
UIImage *image = [UIImage imageNamed:@"Question"];
UIButton *resizableButtonMode=[[UIButton alloc]initWithFrame:CGRectMake(80, 320, 180, 40)];
[resizableButtonMode setTitle:@"iOS6" forState:UIControlStateNormal];
[resizableButtonMode addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
// 設置上左下右邊距
CGFloat topMode= image.size.height * 0.5;
CGFloat leftMode= image.size.width * 0.5;
CGFloat bottomMode= image.size.height * 0.5;
CGFloat rightMode= image.size.width * 0.5;
UIEdgeInsets edgeInsetsMode= UIEdgeInsetsMake(topMode, leftMode, bottomMode, rightMode);
// 拉伸圖片
UIImage *edgeModeImage = [image resizableImageWithCapInsets:edgeInsetsMode resizingMode:UIImageResizingModeStretch];
// UIImage *edgeModeImage = [image resizableImageWithCapInsets:edgeInsetsMode resizingMode:UIImageResizingModeTile];
//設置圖片
[resizableButtonMode setBackgroundImage:edgeModeImage forState:UIControlStateNormal];
[self.view addSubview:resizableButtonMode];
項目GitHub地址:https://github.com/SmallElephant/iOS-FEImageStrech
