iOS-图片拉伸技巧
iOS开发中我们会遇到渐变的背景,内容可变的流式标签,聊天气泡(QQ聊天气泡),由于内容是可变的,宽度和高度同样可变,这样就是导致每次出现的尺寸与之前不一样。如果是需要设置的比较的多,估计美工会烦死,同样也会额外增加的内存开销,所以这个知道一点图片拉伸的技巧会师我们的能使我们APP更加高效,代码更加简洁,事半功倍~从设置的角度来有四种方法可以实现~
Assets设置
首先我们有一个不规则的气泡按钮,大小是35*30,Slices选中水平和垂直方向的距离,宽高设置为1
设置完成之,我们设置Button的背景图片看下加载效果:
1 2 3 4 5 6 | 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中设置,我们先来看一下实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | //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说明:
1 2 3 4 5 6 7 8 9 | @ 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与之前的方法一样,同样是通过重置产生新的图片:
1 | - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(5_0); // create a resizable version of this image. the interior is tiled when drawn. |
UIEdgeInsets基本上UI中比较常见:
1 2 3 | 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; |
图片效果参考模拟器的第三个按钮,设置代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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:
1 | - (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode NS_AVAILABLE_IOS(6_0); // the interior is resized according to the resizingMode |
UIImageResizingMode说明:
1 2 | typedef NS_ENUM(NSInteger, UIImageResizingMode) { UIImageResizingModeTile,平铺模式,通过重复显示UIEdgeInsets指定的矩形区域来填充图片拉伸模式,通过拉伸UIEdgeInsets指定的矩形区域来填充图片 |
实际效果参考上图中的最后一个按钮:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
出处:http://www.cnblogs.com/xiaofeixiang
说明:博客经个人辛苦努力所得,如有转载会特别申明,博客不求技惊四座,但求与有缘人分享个人学习知识,生活学习提高之用,博客所有权归本人和博客园所有,如有转载请在显著位置给出博文链接和作者姓名,否则本人将付诸法律。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探