1.背景自适应且不失真问题的存在

制作自适应背景图片是UI开发的一个广泛问题,也是界面设计师渴望解决的问题,我相信我们彼此都深有体会。
      比如:

1.列表的背景图一定,但是列表的高度随着列表数据项会发生变化;

2.标题栏的背景,无论横屏还是竖屏,高分辨率还是低分辨率,都能自动填充满,而且不失真等等背景问题。
      根据以往的经验,我们一般采用先切图后拼凑的做法,这种做法本来我想在这里和大家介绍一下,其实有的时候还是很有用的,但是说起来会比较麻烦,就不说这个非重点了,略去,如果大家真的要介绍,在回复中说明,我再考虑一下。
     Android针对这种情况,专门制作了一种.9.PNG格式来解决这个问题。

2.9.PNG格式。
      我不想在这里过多的讨论PNG格式的定义问题。但是.9.PNG确实是标准的PNG格式,只是在最外面一圈额外增加1px的边框,这个1px的边框就是用来定义图片中可扩展的和静态不变的区域。特别说明,left和top边框中交叉部分是可拉伸部分,未选中部分是静态区域部分。right和bottom边框中交叉部分则是内容部分(变相的相当于定义看一个内边距,神似padding功能,后面我会单独介绍一下),这个参数是可选的, 如下图。    
     

在Android中以9.PNG格式的图片未背景,则能够自定义拉伸而不失真,比如系统的Button就是一个典型的例子。其实呢,无论是left和top,还是right和bottom都是把图片分成9块 (边角四块是不能缩放的,其他的四块则是允许缩放的),所以叫做9.PNG。

3. 使用Draw9Patch.jar制作9.PNG图片之定义拉伸区域。
      前面已经了解到9.PNG格式的工作方式,下面我们使用谷歌提供的Draw9Patch(运行android-sdk-windows\tools目录下的Draw9Patch.bat)来制作.9.PNG图片。
      第一步:准备要拉伸的图片。
                                                            
      非常小的一张图片,我希望以此为背景,中间部分填充文章内容。
      第二步:制作.9.PNG图片
      打开Draw9Patch,把图片拖进去,如下:

      默认的拉伸是整体拉伸,其实边框部分我们并不想拉伸,好,我们自己来定义拉伸区域,如下图:

然后点击File,导出为content.9.png。
       第三步:在layout文件中使用制作的 .9.PNG图片.
       新建工程Draw9Patch,默认主Activity为Draw9PatchActivity.java:

@Override

public void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

}

我们把content.9.png文件拷贝到/res/drawable文件夹下,打开/res/layout目录下的main.xml,申明如下: >

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="#777"

android:padding="8dip"

>

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="正文:A NinePatchDrawable graphic is a stretchable bitmap image."

android:background="@drawable/content"

android:textColor="#000"

/>

</LinearLayout>

如图,

我们修改text,

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:background="#777"

android:padding="8dip"

>

<TextView

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="正文:A NinePatchDrawable graphic is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the View in which you have placed it as the background. A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border."

android:background="@drawable/content"

android:textColor="#000"

/>

</LinearLayout>

如图,

可以看出,边框非常的清晰。下图是未使用.9.PNG的对比图,而且也不是我们要的效果:

      到这里为止,我们已经基本会制作.9.PNG图片了。为了知识体系的全面性和深入性,我们继续。

4.使用Draw9Patch.jar制作9.PNG图片之定义内容区域。
      是不是觉得文字和边距挨的太近,好,我们使用right和bottom边的线来定义内容区域,来达到增大内边距的目的。

      我们定义了一个很小的内容区域,其他的地方则自动充当边框,从而使内边距显的很大,如下图,

      在这里,我要特别说明,一开始为了增大内边距,很容易惯性思维,在<TextView>中申明android:padding="10dip" 之类的,我在这里劝告朋友们不要这么做,一是你将无法预知你的显示,二是这比较混淆,因为设置内容区域就是确定padding,所以我在前面部分说他们是神似。我个人认为通过内容区域设定padding比在布局xml中定义padding更优雅,更简洁!
      关于Draw9Patch工具的其他使用说明,我在次不再累述,因为要说的话太多,为了节省篇幅,请参考官方文档。

5.制作.9.PNG的高级技巧。
       对于初学Draw9Patch的人来说,这可以算是高级技巧,那就是:拉伸区域,可以不是连续的,可以不止一块,而且是和自定义的边框线的长度成正比。
       直接上图说明:

6.SDK中如何处理9.PNG图片。
      SDK专门针对9.PNG做了定义和处理,这里我们只是做个简单的流程分析,Bitmap在读取图像流数据的时候,会把判断图片的NinePatchChunk(9Patch数据块),如果NinePatchChunk不为空,则是NinePatchDrawable,NinePatchDrawable则又会交给NinePatch处理:

setNinePatchState(new NinePatchState(

new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"),

padding, dither), r);

NinePatch检验成功则调用本地方法,绘制出最终的图片:

nativeDraw(canvas.mNativeCanvas, location,

mBitmap.ni(), mChunk, paint != null ? paint.mNativePaint : 0,

canvas.mDensity, mBitmap.mDensity);

7.android系统中大量应用了9.PNG图片。
     通过解压随便一个rom,找到里面的framework_res.apk,里面有大量的9.PNG格式文件,被广泛的应用起来,比如常见的有:
     按钮:  
     解锁:  
     下拉框:  
     标题栏:
     Toast:
      还有搜索,键盘,放大缩小控件,时间加减等等,我就不一一列举。

8.最后送上一些图例,以飨读者,以做后鉴:
 
赏图1 本人之作

 赏图2 下拉按钮

赏图3 文章头部背景 

赏图4 系统头部背景

赏图5 再来一个头部背景 
谢谢大家的支持。

9.PNG的制作的更多相关文章

  1. 【AR实验室】ARToolKit之制作自己的Marker/NFT

    0x00 - 前言 看过example后,就会想自己动动手,这里改改那里修修.我们先试着添加自己喜欢的marker/nft进行识别. 比如我做了一个法拉利的marker: 还有网上找了一个法拉利log ...

  2. Unity3d学习 制作地形

    这周学习了如何在unity中制作地形,就是在一个Terrain的对象上盖几座小山,在山底种几棵树,那就讲一下如何完成上述内容. 1.在新键得项目的游戏的Hierarchy目录中新键一个Terrain对 ...

  3. 制作类似ThinkPHP框架中的PATHINFO模式功能

    一.PATHINFO功能简述 搞PHP的都知道ThinkPHP是一个免费开源的轻量级PHP框架,虽说轻量但它的功能却很强大.这也是我接触学习的第一个框架.TP框架中的URL默认模式即是PathInfo ...

  4. 使用Visual Studio SDK制作GLSL词法着色插件

    使用Visual Studio SDK制作GLSL词法着色插件 我们在Visual Studio上开发OpenGL ES项目时,避免不了写Shader.这时在vs里直接编辑shader就会显得很方便. ...

  5. 利用CSS中的:after、: before制作的边三角提示框

    小颖昨天分享了一篇参考bootstrap中的popover.js的css画消息弹框今天给大家再分享一篇使用:before和:after伪元素画消息弹框的CSS. 画出来是介个酱紫的: 有没有觉得画的萌 ...

  6. Photoshop将普通照片快速制作二次元漫画风格效果

    今天为大家分享Photoshop将普通照片快速制作二次元漫画风格效果,教程很不错,对于喜欢漫画的朋友可以参考本文,希望能对大家有所帮助! 一提到日本动画电影,大家第一印象肯定是宫崎骏,但是日本除了宫崎 ...

  7. 前端制作动画的几种方式(css3,js)

    制作动态的网页是是前端工程师必备的技能,很好的实现动画能够极大的提高用户体验,增强交互效果,那么动画有多少实现方式,一直对此有选择恐惧症的我就总结一下,以便在开发的时候选择最好的实现方式. 1.css ...

  8. JS图片上传预览插件制作(兼容到IE6)

    其实,图片预览功能非常地常见.很意外,之前遇到上传图片的时候都不需要预览,也一直没有去实现过.现在手上的项目又需要有图片预览功能,所以就动手做了一个小插件.在此分享一下思路. 一.实现图片预览的一些方 ...

  9. 用FSM一键制作逐帧动画雪碧图 Vue2 + webpack

    因为工作需要要将五六十张逐帧图拼成雪碧图,网上想找到一件制作工具半天没有找到,就自己用canvas写了一个. 写成之后就再没有什么机会使用了,因此希望有人使用的时候如果遇到bug了能及时反馈给我. 最 ...

  10. C#制作简易屏保

    前言:前段时间,有个网友问我C#制作屏保的问题,我瞬间懵逼了(C#还可以制作屏保!).于是我去查阅相关资料,下面把C#如何制作屏保的过程及我学习过程的心得也记录下来,希望对需要的人能有帮助. 基本思路 ...

随机推荐

  1. useful commands for docker beginner

    You may want to add my wechat public account or add my technical blog's RSS feed This list is meant ...

  2. Leetcode 笔记 116 - Populating Next Right Pointers in Each Node

    题目链接:Populating Next Right Pointers in Each Node | LeetCode OJ Given a binary tree struct TreeLinkNo ...

  3. java遇到 Check $M2_HOME 问题 解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.

    步骤: 1.添加M2_HOME的环境变量 2.Preference->Java->Installed JREs->Edit 选择一个jdk 3.添加 -Dmaven.multiMod ...

  4. 关于百度编辑器UEditor的一点说明

    大家在使用的时候要特别注意editor_config.js中的“URL”这个参数 我的理解:1.这个参数是editor整个结构的总路径          2.首先要把这个路径配置好了.才能正常的显示, ...

  5. PHPUnit笔记

    PHPUnit是一个面向PHP程序员的测试框架,这是一个xUnit的体系结构的单元测试框架. 复杂的项目,通过单元测试能够快速排查bug,有效减少bug的产生.简单的项目,使用php自带的var_du ...

  6. Android开发学习之路-动态高斯模糊怎么做

    什么是高斯模糊? 高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop.GIMP以及Paint.NET等图像处理软件中广泛使用的处理效果,通常用它来减少图像噪 ...

  7. Python的魔法函数之 - __len__,__getitem__,__setitem__,__delitem__

    # 对象作为len()函数的参数是必须实现该方法 __len__ # 使用类似字典方式访问成员时必须实现 dic['pro_name'] __getitem__ # 使用类似字典方式设置成员时必须实现 ...

  8. ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

    在<管道是如何处理HTTP请求的?>中,我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.这样一 ...

  9. Android学习路线

    第一阶段:Java面向对象编程 1.Java基本数据类型与表达式,分支循环. 2.String和StringBuffer的使用.正则表达式. 3.面向对象的抽象,封装,继承,多态,类与对象,对象初始化 ...

  10. Log4net入门(ASP.NET MVC 5篇)

    在前4篇Log4net入门文章中,我们讲述了log4net的一些简单用法,在这一篇中我们主要讲述如何在ASP.NET MVC 5项目中将日志信息写入SQL Server数据库中. 一.创建最简单的AS ...