iOS图像拉伸代码方法——withCapInsets

字数 2567阅读 449

上回书介绍了Android平台用于拉伸的.9图,程序通过识别.9图中的1像素边界来达到自动拉伸图片的效果。那么在iOS平台中,图片拉伸的原理和思路基本与.9图相似,也是通过设定上下左右的安全区来定义图片拉伸的区域,只不过在iOS平台上,拉伸图片的工序基本是需要程序猿来达成,通过代码或者可视化的方式来设定安全区。

本文中将介绍代码实现图片拉伸的方式。

目前,代码拉伸的方式有3种,分别是iOS5之前、iOS5之后、iOS6之后的三种方法,但iOS5的方法已经过期,iOS6之后的方法比iOS5之后的方法更优,因此,本文只介绍iOS6之后最新的方法。想要了解iOS5之前、iOS5之后的方法,请在后台回复001查看本文的番外篇。





在苹果开发者网站中,有关于设定可拉伸图片的部分:

([UIImage - UIKit | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiimage))



定义可拉伸图像


笔者翻译:

定义可拉伸图像

可拉伸图像划定了可以被复制的区域,在此区域内,底层图像数据可以以一种美观的方式被复制。可拉伸图像经常用来创建可拉伸或缩小的背景,以填充可用的区域。

你可以通过给图像添加内嵌(insets)来将它定义一个可拉伸图像,具体可以使用两种方法,即resizableImage(withCapInsets:) 或 resizableImage(withCapInsets: resizingMode:)。内嵌(insets)将图像划分成两个或多个部分。给每个内嵌(insets)区域指定非零的值,将图像分为9个部分,如图1所示。

图1 使用内嵌(insets)来定义可拉伸图像


使用内嵌(insets)来定义可拉伸图像


每一个内嵌(insets)定义了图像上不被拉伸的部分,在图片顶部和底部的内嵌(insets)区域将保持一个固定的高度,在左边和右边的内嵌(insets)区域将保持一个固定的宽度。图2展示了当图像在填充可用区域时,9个部分各自将如何拉伸。图像的四角不会有大小变化,因为它们均处于纵向和水平的内嵌(insets)区域内。


图2  九宫格图像的拉伸区域


九宫格图像的拉伸区域


不难看出,iOS平台上的图像拉伸与Android平台中的图像拉伸原理十分相似,都是将图像划分为9宫格,在各个方法做拉伸,只不过Android靠点九图中的黑色边线来标识拉伸的部分,iOS则利用代码或者是在编译器中进行可视化的编辑。具体来说是通过给图像定义四个内嵌(insets),从而将图像划分为九宫格再进行拉伸。

接下来将介绍上文提到的两种拉伸方法






resizableImage(withCapInsets:)

官当文档:

resizableImage(withCapInsets:)


笔者翻译:

实例方法:resizableImage(withCapInsets:)

创建并返回一个设定有指定端盖内嵌(cap insets)的新图片对象

声明:

func resizableImage(withCapInsets capInsets: UIEdgeInsets) -> UIImage

参数:

capInsets —— 端盖内嵌(cap insets)的数值

返回数值:

一个设定有指定端盖内嵌(cap insets)的新图片对象

描述:

你可以使用这个方法来给图像添加端盖内嵌(cap insets),或是改变一个图像已有的端盖内嵌(cap insets)。无论哪种情况下你都会得到一个新的图像,同时原始图像将不受影响。比如说,你可以使用这个方法为一个带边界和圆角的按钮创建背景图像:当按钮被缩放时,图像的四角将不会改变,但图像的边界和中间将拉伸以填充新的大小。

iOS不同的渲染技术有着不同的表现特征,这取决于图像中每个拉伸区域的大小:

如果拉伸区域有1像素宽或高,则横向拉伸区域是1像素宽,纵向拉伸区域是1像素高,换言之,图像中心区域为1x1像素大小,iOS将通过拉伸这1像素来绘制新的图像。这种模式将有最快的表现(在端盖内嵌(cap insets)非零的情况下)。

如果拉伸区域的宽或高大于1像素,iOS将以平铺(tiling)的方式填充。这种模式表现相对较慢,但对于纹理图像(非固色)的填充来说非常实用。

如果整个图像都被拉伸,这种情况下capInsets的参数为UIEdgeInsetsZero,它的尺寸也会大于1x1像素,iOS将通过平铺整个图像来绘制新图像。这种模式在端盖内嵌(cap insets)非零的情况下,将会比平铺(tiling)的方式更快。

如果要直接控制拉伸的模式,请使用resizableImage(withCapInsets: resizingMode:)方法。



在方法介绍中提到的参数capInsets是UIImage的一个属性,用以设定图像的端盖内嵌(cap insets)




capInsets

官当文档:

capInsets

笔者翻译:

实例属性:CapInsets,即端盖(end-cap)内嵌(insets)。

声明:

var capInsets: UIEdgeInsets { get }

描述:

端盖指定了在图片拉伸时,不会被拉伸的区域。该技术应用于按钮以及其他可调整大小的界面图片元素。当带有端盖的按钮被拉伸时,只会被拉伸按钮的中部,也就是各端盖之间的区域。而端盖则会保持其原始的大小和外观。

CapInsets属性指定了4个端盖的大小,中间(可拉伸)区域由所有不包括在端盖的像素组成,这些像素将会以tiled(瓷砖)的方式从左向右、从上到下来填充其余的空间。

在一个不可拉伸的图片中,CapInsets属性被设置为UIEdgeInsetsZero,因而图片不会使用端盖,这也导致在拉伸时是整个图片作为整体被拉伸。若想要创建一个CapInsets属性不为零的图片,则使用resizableImage(withCapInsets:)方法。如果你的应用程序将UIEdgeInsetsZero指定为CapInsets的参数,那么就将整个图片设为平铺(tiled)。

CapInsets即是包含端盖(end-cap)图片,end up(端盖)在iOS中是指在图片中不被拉伸的区域。


端盖(end-cap)


而CapInsets的变量类型是UIEdgeInsets.




UIEdgeInsets

官当文档:

UIEdgeInsets

笔者翻译:

数据结构:UIEdgeInsets,即界面的嵌入式间隔距离。

概述:

边界内嵌的数值将用于缩小或扩展矩形所表示的区域。通常,边界内嵌应用于界面布局,以此调整界面框架。正值使框架嵌入(或缩小),负数使框架外凸(或扩大)。

同时请阅读 UIEdgeInsetsMake(_:_:_:_:)和UIEdgeInsetsZero


具体设定内嵌的数值需要应用UIEdgeInsetsMake(_:_:_:_:)或UIEdgeInsetsZero




UIEdgeInsetsMake(_:_:_:_:)

官当文档:


UIEdgeInsetsMake(_:_:_:_:)

笔者翻译:

函数:UIEdgeInsetsMake(_:_:_:_:),为按钮或界面创建一个边界内嵌

声明:

func UIEdgeInsetsMake(

_ top: CGFloat, //顶端高度

_ left: CGFloat,        //左端宽度

_ bottom: CGFloat, //底端高度

_ right: CGFloat) -> UIEdgeInsets //右端宽度

参数:

Top——对象的顶端内嵌

Left——对象的左端内嵌

Bottom——对象的底端内嵌

Right——对象的右端内嵌

返回值:按钮或界面的内嵌

描述:内嵌(insets)是在矩形外的边界,正值代表边界靠近矩形中心,负值代表边界远离矩形中心。


而若想将上下左右的内嵌区域都设为0,则可以直接设置为UIEdgeInsetsZero




UIEdgeInsetsZero

官当文档:

UIEdgeInsetsZero

笔者翻译:

全局变量:UIEdgeInsetsZero

上下左右区域均为0的边界内嵌

声明:

const UIEdgeInsets UIEdgeInsetsZero;

总的来看,将可拉伸区域设置为1x1像素大小是表现最好的方案。

而文中提到的resizableImage(withCapInsets: resizingMode:)方法则可以直接控制拉伸时的填充模式,事实上,它只比resizableImage(withCapInsets:) 多了一个控制拉伸的填充模式参数。





resizableImage(withCapInsets:reizingMode:)

官当文档:

resizableImage(withCapInsets:reizingMode:)

笔者翻译:

实例方法:resizableImage(withCapInsets: resizingMode:)

创建并返回一个设定有指定端盖内嵌(cap insets)及拉伸模式的图片对象

声明:

func resizableImage(withCapInsets capInsets: UIEdgeInsets,

resizingMode: UIIamgeResizingMode) -> UIImage

参数:

capInsets —— 端盖内嵌(cap insets)的数值

resizingMode —— 图像内部的拉伸方式

返回数值:

一个设定有指定端盖内嵌(cap insets)及拉伸方式的新图片对象

描述:

这个方法可以明确声明新图像对象的拉伸方式,除此之外,与同级的resizableImage(withCapInsets:) 完全一样。除非你想指定图像的拉伸模式,才可用它代替同级的resizableImage(withCapInsets:) 方法。


拉伸模式的变量类型是UIImageResizingMode




UIImageResizingMode

官当文档:(Swift语言)

UIImageResizingMode(Swift语言)


笔者翻译:

枚举型:UIImageResizingMode,图像拉伸的具体伸缩模式

case title:平铺

图像在拉伸时采用平铺模式填充,也就是说,原始图像内部区域将会被重复平铺,以此填充新图像的大小。

case stretch:拉伸

图像在拉伸时采用拉伸模式填充,也就是说,原始图像内部区域将会被直接拉伸,以此填充新图像的大小。

注:用ObjC写的话,参数则为UIImageResizingModeTile、 UIImageResizingModeStretch

UIImageResizingMode(ObjC语言)




欢迎关注我的微信公众账号:用心玩手机


用心玩手机

推荐阅读更多精彩内容