在Android中创建和使用9-patch图像

51

我最近听说了9-patch图像。我知道它是由9个平铺且可拉伸的部分组成的。我想了解更多关于它的信息。

  • 我如何创建一个9-patch图像?

    是否有任何工具?我可以从AndroidSDK或代码中创建吗?

  • 9-patch相对于常规png的主要优势是什么?

    (它是否可以根据屏幕动态/自动地进行拉伸?)

8个回答

45
SDK和Android Studio都附带了“Draw 9-patch”工具(在SDK工具文件夹中为“draw9patch”),这是一个简单的编辑器。这里有一个更好的,它也是开源的。它有一个简单但聪明的默认图像。 官方文档随着时间的推移已经得到了改善。总之,九宫格图像最重要的优点是可以指定(非连续的)区域进行缩放:
一个NinePatch图形是标准的PNG图像,其中包含额外的1像素边框。它必须以9.png扩展名保存在项目的res/drawable/目录中。使用边框来定义图像的可拉伸和静态区域。通过在边框的左侧和顶部绘制一个(或多个)1像素宽的黑线来指示可拉伸部分(其他边框像素应完全透明或白色)。您可以拥有任意数量的可拉伸部分。可拉伸部分的相对大小保持不变,因此最大的部分始终保持最大。您还可以通过在右侧和底部绘制一条线来定义图像的可选可绘制部分(有效地是填充线)。如果View对象将NinePatch图形设置为其背景,然后指定视图的文本,它会拉伸自身,以使所有文本仅占用由右侧和底部线指定的区域(如果包括)。如果未包括填充线,则Android使用左侧和顶部线来定义此可绘制区域。

Diagram of the border parts of a 9-patch image

但是文档缺乏好的例子。这个教程在结尾处有一些很好的例子,回答了你问题的第二部分,解释了缩放是如何工作的 - 不仅仅是针对按钮 - 还有框架,并且它有一个完整的示例项目,你可以下载并使用。

1
这个链接的教程有一个带有可工作代码的项目 - 没有其他文档可以比拟.. 这真的很重要,谢谢! - Gene Bo

24

大多数示例讨论创建9-patch图像,但实现细节通常被留在高层次上。

尼克(Nick)在上面的帖子 - 使用好的9-patch教程提供了一个可下载的工作项目文件,解决了问题。

以下是对我有用的主要实现细节(一旦您准备好9-patch图像)

  1. 引用名称为 drawable 的可绘制对象,但不包括 .9.png(Eclipse 中的自动完成会照顾到这一点)

  2. 确保主 /drawable 文件夹下只有1个图像(而不是每个 dpi 文件夹的版本)

  3. 必须使用 :background 来指定图像,而不是 :src (这让我卡住了一段时间)

    android:background="@drawable/splash_logo"

  4. 确保包含图像的布局和图像本身正在使用:

    android:layout_width="fill_parent"
    android:layout_height="fill_parent"


你在哪个XML元素上指定:background,在什么场景下你尝试使用了 fill_parent 用于 layout_heightlayout_width两个属性?肯定只需要其中一个是 fill_parent 吧? - Tash Pemhiwa

9
当你在主要搜索引擎中搜索“android 9-patch tool”时,第一个结果是Android开发者文档页面上的draw9patch工具。我该如何创建9-patch图像?是否有任何工具?我能否从AndroidSDK或代码中创建它?
Android开发者文档包含其他页面,描述了九宫格PNG文件。该文档包括以下内容:
九宫格图形是可伸缩的位图图像,Android将自动调整大小以适应您放置为背景的View中的内容。九宫格的一个示例用途是标准Android按钮使用的背景 - 按钮必须拉伸以适应各种长度的字符串。九宫格相对于常规png的主要优点是什么?(它是否可以根据屏幕动态/自动地拉伸?)

6

3

1.什么是NinePatch图片?

NinePatch图片是PNG图像,标记可拉伸的部分。它们的扩展名为image_name.9.png

2.它们在安卓项目中存储在哪里?

res/drawable/image_name.9.png

3.如何为您的安卓应用程序创建NinePatch图像?

Android SDK包括一个WYSIWIG draw9patch.jar 工具,该工具位于您的Android SDK /tools文件夹内。

enter image description here


1

步骤1,由于您还不熟悉,首先准备一个xxxhdpi的png大图像来玩耍。

步骤2,该图像所需的可扩展区域必须尽可能地缩短(通过删除冗余/重复的颜色部分),因为9-patch没有“减少”图像的功能,只能“扩展”图像。

我个人使用ImageMagick命令行工具进行转换,例如:

convert -trim 'my_image.png' png32:my_image_trim.png #trim extra transparent surrounded image
rm lala*; convert my_image_trim.png -crop 310  +repage  +adjoin  png32:lala%02d.png #cut redundant/repeat center part
convert +append lala02.png lala05.png png32:out_right.png #append left/right images side by side
convert -resize 144x144\! out_right.png png32:my_image.png #resize to the desired dpi

转换时有一个陷阱:我必须以png32为前缀,否则将得到黑色的9-patch图像,请参见this thread

步骤3,将图像复制到Android Studio drawable中,然后右键单击并选择菜单项“创建9-Patch文件...”。将生成一个带有相同图像名称的.9.png新图像。现在可以删除原始图像。在重构更名备份时要小心,因为它也会重命名XML图像ID,并使您想知道为什么9-patch图像不起作用,因为XML仍然引用非9-patch图像。

步骤4,左侧和顶部的2条黑线形成可扩展的矩形区域,而右侧和底部的2条黑线形成文本矩形区域。

随着文本增长,您的图像大小将在声明的可扩展区域上增加。而文本区域意味着只允许在该区域内输入文本。

对于简单的用法,您无需从头开始绘制黑点/线,如果您的9-Patch图像是由Android Studio生成的,则已经存在于图像的顶部、左侧、底部、右侧后面的4条黑线。如果您看不到那些线条,请“放大”。

两条黑线的初始位置,一条垂直,一条水平,都表示可扩展区域:

  • 左侧垂直线的初始位置在左上到左下之间
  • 顶部水平线的初始位置在左上到右上之间

两条黑线的初始位置,一条垂直,一条水平,都表示文本区域:

  • 右侧垂直线的初始位置在右上到右下之间
  • 底部水平线的初始位置在左下到右下之间

以上是拖动缩短长度、调整这些线的起始位置和结束位置之前的黑线原始位置。

可扩展区域和文本区域可以根据您的需要而不同。但是通常情况下,可扩展区域应该等于或小于文本区域,一个经典的例子就是聊天气泡图像:

enter image description here

上面的图片上下黑线宽度相等,但右侧黑线高于左线,这也意味着文本始终保持在底部曲线的一半,无论是最小尺寸还是扩展尺寸。并且它只在文本区域内扩展。
现在你将会知道9-Patch的两个好处:底部和右侧的线共同形成一个文本区域,完美地确保文本永远不会溢出图像曲线的外部!而且定义了哪个部分的文本区域负责随着文本增长而扩展图像,同时保持曲线不缩放。
将鼠标悬停在线条上将能够看到像素的x、y位置,这有助于测量两条线是否相等或者位置是否较低。
拖动时应记住线条的位置,因为左线可以拖到右侧,右线可以拖到左侧,你可能会忘记哪条线是可扩展线,哪条线是文本线。
有2个重要的复选框你应该勾选,即“显示补丁”和“显示错误补丁”复选框。
在“显示错误补丁”复选框中,如果您绘制的可展开区域覆盖了图像的曲线而不是直线,则会将该区域标记为红色以警告您。您可以缩小您的线条以消除该红色警告,或者忽略它。请注意,红色警告可能会误导,实际上可能是由相反的线引起的,在这种情况下,您需要缩小相反的线以消除该红色警告。
第五步,在xml中,您可以像下面这样将该图像作为TextView背景引用,使用wrap_content使其可扩展:
<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/your_9_patch_image_name_excluded_.9"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
    <2nd TextView />
</LinearLayout>

当第一次尝试使用它时,请确保TextView或其父布局没有填充,否则您可能会想知道为什么不按预期工作。
按钮背景示例:
    <Button
        android:id="@+id/btn2"
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:background="@drawable/your_9_patch_image_name_excluded_.9"
        android:layout_gravity="center"
        />

1

9-patch相比普通png的主要优势

9 Patch图像实际上是可拉伸、可重复使用的图像,缩小到最小尺寸。在不同屏幕尺寸下,图像不会延展和失去比例。另一个最大的优势是内存。

相同大小的内存可以用于不同尺寸的设备。设计良好的9-patch图像较少出错且具有高度的可重用性。

https://developer.android.com/studio/write/draw9patch.html


1
不可重复,只可伸缩。 - Richard Lalancette

1

这是一个好工具: 点击这里。

9 Patch 图像是可拉伸、可重复的图像,缩小到它们最小的尺寸。最简单的例子是,如果你把一个圆角 div 切成 9 个正方形,就像玩井字棋一样。四个角不会改变大小,但是静态,而其他5个部分将被拉伸或重复,以使整个图像适当地缩放。

通过这种解释和 CSS3 的出现,你可能认为没有理由使用 9 Patch 图像,但是“9 Patch”这个名称是一个错误。这些图像可以被切割成更小的块。

9 Patch 图像包含了一个索引,用 1px 的边框添加到图像中来表示哪个部分是什么。边框中的颜色确定一个部分是静态的(不缩放),还是拉伸,或者是重复的。

谷歌幻灯片:https://docs.google.com/present/view?id=dc7ghz8w_34f8338rcg

另外,关于9-patch图像的Android开发者信息,请参见:http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接