Android的9-Patch图应该怎么用

1,667 阅读5分钟

1. 简介

9-Patch这种图形对应于Android中的NinePatchDrawable类型

A resizeable bitmap, with stretchable areas that you define. This type of image is defined in a .png file with a special format.

NinePatchDrawable  |  Android Developers (google.cn)

根据官方文档的介绍,可以知道这是一个可以拉伸位图,并且具体的拉伸区域可以由开发者自定义

1.1. 特点

  • 9-Patch图形是标准的PNG格式的图片,包含额外的1像素用作边框
  • 必须使用.9.png的扩展名保存到项目的res/drawable/目录下
  • 分为可拉伸区域静态区域
  • 定义可选可绘制部分

2. 工具使用(Android Studio 内置的工具)

创建可调整大小的位图(9-Patch 文件)  |  Android 开发者  |  Android Developers (google.cn)

我们经常见到的一种场景,就是像一些聊天对话框的处理

image.png

你想要的效果可能是这样

image.png

但是把png直接怼进去,然后各种玄学加padding、margin摆位置,其实得到的只是这样
写起来既不优雅,看起来又很凑合
四角被拉伸变形内容的位置又不整齐,搞不好还堆出一串谜一般的间距

image.png

其实,分析一下,会发现我们的痛点在于需要解决图形的一部分需要保持形状,同时又要允许内容造成的形变这样的问题,这便是9-Patch大显身手的地方

2.1. 准备素材

首先,将原始的.png图片转换为它对应的9-Patch图片

image.png

这将以原图形为模板,创建对应的9-Patch图片

image.png

对应会生成一个扩展名为.9.png的图片

image.png

也将其放在drawable目录下,原来的图可以删了

image.png

双击打开9-Patch图片看到的是这样一个界面,这便是Android Studio内置的9-Patch工具的工作区,接下来需要在这里进行操作

image.png

2.2. 工作区使用

工作区主要分为左右两块区域,左侧区域用作编辑和绘制,也是我们主要进行操作的区域
右侧区域主要预览图像进行水平竖直拉伸后形变的效果

image.png

2.2.1. 可拉伸区域

使用9-Patch可以对于图片指定可拉伸区域静态区域
可拉伸区域是我们允许发生变形的区域,可以在水平和垂直方向上进行区域的调整 首先,前面提到过,9-Patch的图形在外边框有1像素黑边,也就是上下左右一共4条黑边,如果需要设置可拉伸区域会用到上侧和左侧的黑边

可以看到,水平方向上从两侧进行拖拽,选择顶部的黑线操作,会有一个矩形覆盖住,而在网格的顶部有一条1像素的黑线对应我们覆盖的范围,矩形盖住的区域就是表示允许缩放的内容,现在表示水平拉伸两侧的圆角会保持形状(数值不会,因为刚刚只指定了水平方向)

state.gif

image.png

对照预览右侧水平拉伸的效果图,黑线区域未覆盖圆角区域,则圆角在拉伸中得以保持原来的形状

image.png

接下来,使用相似的手法在垂直的方向上进行操作,这次选择左侧的黑线操作

state.gif

现在可以看到在顶部和左侧对应都有1像素黑线,二者交叉的范围就是最终确定下来的可拉伸范围,除此以外的区域会保持原来的形状

image.png

预览一下,拉伸的效果,垂直方向的形变依然能够保持圆角

image.png

水平和垂直一起拉伸依然会保持圆角

image.png

这便对应了我们的预期,勾选“Show patches”可以查看到红色区域正好就是最终的可拉伸区域

image.png

2.2.2. 内容填充范围

如果不加设置,利用这张图作为背景,使用TextView去填充文字,依然会造成文字直接从左上角的空白处开始填充的情况

勾选“Show Content”,可以看到紫色区域是内容允许填充的范围,初始状态对应的就是整张图片的矩形区域

image.png

接下来,使用刚刚剩下的底部和右侧的黑线控制内容允许填充的范围,操作方式和先前差不多,这次就一次完成了

state.gif

同样是利用水平与垂直方向的交叉部分作为指定区域,现在再次勾选“Show Content”,明显区域只有图形内部的部分了

image.png

现在把它作为TextView的背景,测试一下效果

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:background="@drawable/bg_msg"
    android:text="Hello World"
    android:textSize="36sp">
</TextView>

是不是成功出现在了中央位置

image.png

3. 实际使用

在简单了解了9-Patch图片的一些基础操作和使用后,可以试着将对话气泡做成我们想要的样子

通常情况下,我们的需求是红框的区域不变,以及之前的四个圆角

image.png

接下来,拖动边,确定可拉伸的范围

image.png

根据左侧和右侧的线确定出可拉伸的范围,为图中红色区域

image.png

对应到右侧预览图,红框区域并未变形

image.png

接下来,安排一下内容可用区域,根据右侧和底部的黑线确定,为蓝框区域

image.png

在右侧图上预览一下

image.png

接着像之前一样,放到TextView的背景中,修改内容

image.pngimage.png

可以发现,四周的圆角和底部的三角保持住形状,而其他其余可以拉伸,这也就达到了最终的目的

可绘制对象概览  |  Android 开发者  |  Android Developers (google.cn)