利用9-Patch PNG来实现ListView的圆角显示
jopen
13年前
<p>说到<span>圆角</span>显示,可能很多人的第一反应就是覆盖onDraw方法来自己画个<span>圆角</span>,可能以前写过其它Windows程序,比如Delphi的人会更有这种冲动吧。<br /> 不过在Android中,我们不需要这么麻烦,事实上整个Android系统的UI都是基于<span>Style</span>来实现的,有兴趣的朋友可以去研究一下Android的源码,看看如Button, Radio是如何实现的,就会明白Android的UI体系是非常强大、简单,又有趣的。<br /> 本文会以List View为例来讲解,如何使用<span>Style</span>来实现圆角(想想哪个控件已经是有圆角的了?)。</p> <h3>何为<span>Style</span></h3> <p>Android系统中的UI都是基于一个个的Style来显示的,同1个控件,换1个Style,效果就完全不同了。Style其实就是一堆显示属性的集合,包括文字属性,颜色设置,<span>背景</span>设置,而一堆Style的集合就构成了<span>Theme</span>.</p> <p>尤其值得一提的是Style定义中经常会看到Selector,用于描述1个控件在不同的场景(Normal, Pressed, Disabled)下的显示。如以下的style定义代码:<br /> 文件:drawable/setting_button.xml</p> <pre class="brush:xml; toolbar: true; auto-links: false;"><?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true" android:drawable="@drawable/setting_icon_pressed"/> <item android:state_focused="true" android:drawable="@drawable/setting_icon_pressed"/> <item android:drawable="@drawable/setting_icon_normal"/> </selector></pre> <p></p> <p>这是最简单的selector定义,它的含义是有1个按钮,在pressed或focused时,显示图标 @drawable/setting_icon_pressed,否则显示@drawable/setting_icon_normal,而这个 selector本身就可以用在button的android:background属性中,如:android:background=”@drawable/setting_button”。如此一来,Android就会在你按下按钮的时候自动切换<span>背景</span>图片。</p> <h3>何为<span>9-Patch</span></h3> <p>讲到了<span>背景</span>图片,就必然会联想到图片的大小和缩放问题,总不能不断去麻烦美工MM来帮你修改图的大小吧,更何况我们还要适应Android手机众多的分辨率?<br /> 这就要说到<span>9-Patch</span>了,先来看看Google官方关于这个工具的1个截图:</p> <p><img title="draw9patch工具" border="0" alt="draw9patch工具" src="https://simg.open-open.com/show/8f65b66abecd947bc19b5fa5f910d064.png" width="341" height="300" /></p> <p>首先,这是1个PNG图片。其次,在用draw9patch打开的时候,会自动在边缘添加1个像素点的透明边框。而这个边框就是你的工作范围了,左键点击会添加1个黑点,右键点击会去掉1个黑点,这些黑点连成的线就构成了<span>9-Patch</span>图片的效果。其中:左边和上面表述的是图片缩放的范围,右边和下边表述的是内容的Padding范围。</p> <div> 好像有点不大明白?运行这个工具(在android sdk的tools目录下),并且拖1个PNG图片进去,选中下方的2个Checkbox,再试用一会儿就明白了。 <br /> OK,我们来准备今天这个教程所需要的图片,请美工MM帮你画1个圆角图片吧,但不用切开,图片大小大概在40×40即可,主要是根据你所需要的最小的大小来决定,然后拖到draw9patch中,看下开始的效果。 <p></p> <p><img title="draw9patch开始工作" border="0" alt="draw9patch开始工作" src="https://simg.open-open.com/show/76804dfa1ac794c3f8f9029dc8ff3c4e.jpg" width="220" height="219" /><br /> </p> <p>然后我们在图片边缘点击进行绘制,并且点选下方2个Checkbox,结束时的效果如下图:</p> <p><img title="draw9patch绘制结束" border="0" alt="draw9patch绘制结束" src="https://simg.open-open.com/show/06813c7b8eb1a436dc280f688bc70604.jpg" width="259" height="260" /></p> <p>在使用这个图片时,左右2个绿色区域是会自动的上下拉伸,而上下2个绿色区域会自动的左右拉伸,中间的粉色区域会做4个方向的拉伸,至于4个角嘛,你已经知道了,它们不会缩放。而下方的的黑线表示,控件的内容会从最左边到最右边,几乎不留空隙,右边的黑线表示,控件的内容会在上下各留一些空间。<br /> 好了,将这个文件保存为float_panel.9.png,并保存到res/drawable目录下。记得扩展名必须是9.png,否则不会生效。另外下次你再次编辑这个文件时,draw9patch工具就不会再添加黑边了。</p> <h3>编写布局文件</h3> <p>文件:res/layout/coner_round_list_activity.xml</p> <pre class="brush:xml; toolbar: true; auto-links: false;"><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:text="Coner Round List View Sample" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <ListView android:id="@+id/conerRoundListView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:paddingBottom="10dp" android:layout_margin="10dp" android:background="@drawable/float_panel" android:layout_weight="1" android:cacheColorHint="#FFEDEDED" android:divider="#00EDEDED" /> </LinearLayout></pre> <p></p> <p>略做讲解:layout_margin是为了留点空间,更容易看出效果,backgroud就是用来设置9patch图片的。cacheColorHint的颜色与我所选用的<span>背景</span>图的颜色一样,可以确保滚动时的item底色不会变化。android:divider是用来控制分隔线的,这里我们不需要它,否则效果会受影响。(试试去掉这个属性?)</p> <h3>编写Activity类</h3> <p>好了,我们写个类来使用这个布局文件吧,老规矩,从API DEMO中COPY了一个很长的String[]定义,并且使用ArrayAdapter来显示数据</p> <pre class="brush:java; toolbar: true; auto-links: false;">public class ConerRoundListActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.coner_round_list_activity); ListView arrowList=(ListView) findViewById(R.id.conerRoundListView); arrowList.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mStrings)); } private String[] mStrings = { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi", ... }; }</pre> <p></p> 平淡无奇的代码,这也是我为什么说在Android中设置圆角是一件很容易的事情。 <br /> 最后,在运行程序之前,我们还要为这个activity进行一下额外的配置,打开manifest文件,修改或添加这个activity的定义如下: <pre class="brush:xml; toolbar: true; auto-links: false;"><activity android:name=".conerround.ConerRoundListActivity" android:label="Coner Round List" android:theme="@android:style/Theme.Light" /></pre> <p></p> <p>注意,我为这个activity指定了theme为android自带的<span>Theme</span>.Light,原因是这个theme的配色与我选的图片比较匹配(至少它的文字颜色是黑的,如果是默认<span>Theme</span>的白色,在背景图上的显示就看不清了)。</p> <p>运行吧,最终的效果图如下:</p> <p><img title="圆角ListView运行结果" border="0" alt="圆角ListView运行结果" src="https://simg.open-open.com/show/579ded48db51f2293ada80805f3ebb8f.jpg" width="320" height="455" /></p> <h3>总结</h3> <p>Style, <span>9-Patch</span> PNG, Background,这些元素混在一起,构成了Android在UI方面非常强大的功能,而且它还很简单,有兴趣的话可以读下源码,会对UI元素的使用有更深的了解,也许自己弄1个漂亮的<span>Theme</span>来供多个程序使用是一个不错的主意。</p> <p>文章出处:<a href="/misc/goto?guid=4959499961996997729" rel="nofollow">http://www.learningandroid.net/blog/advance/9-patch-listview-coner/</a></p> </div>