下面我们通过一个实际的例子,来说明定制按钮的大致过程。
1. 在Eclipse中创建一个Android项目
项目取名为CustomizeButton,然后点击按钮Next,
选中Android2.1,然后点击按钮Next,
将项目包名设定为com.pat.customizebutton,其他保持不变,然后点击按钮Finish。
2. 在main.xml中增加三个按钮,使之如下:
<?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" >
<Button
android:id="@+id/samllbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Small"
/>
<Button
android:id="@+id/mediumbutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="MediumMediumMedium"
/>
<Button
android:id="@+id/largebutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="LargeLargeLargeLargeLargeLargeLargeLarge"
/>
</LinearLayout>
3. 运行该应用程序,得到结果:
到这里,一切表现算是良好。
现在,假定我们要将三个按钮的背景颜色改为黄色,我们需要怎么做呢?很自然就会想到在main.xml中或者在CustomizeButtonActivity.java中进行按钮属性的改动,在这里,我们不妨在CustomizeButtonActivity.java中来改变按钮的属性。代码大致如下:
public class CustomizeButtonActivity extends Activity
{
private Button smallButton;
private Button mediumButton;
private Button largeButton;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
smallButton = (Button)findViewById(R.id.samllbutton);
mediumButton = (Button)findViewById(R.id.mediumbutton);
largeButton = (Button)findViewById(R.id.largebutton);
smallButton.setBackgroundColor(Color.YELLOW);
mediumButton.setBackgroundColor(Color.YELLOW);
largeButton.setBackgroundColor(Color.YELLOW);
}
}
运行程序,得到如下结果:
很显然,这不是我们想要的结果:
1) 所有的按钮全都挤在了一块
2) 原来按钮上的四个圆角都变成的方角(假定你需要的是圆角而不是方角)
当然,在实际编程中不只是改变按钮颜色那么简单,你可以需要有一个背景图片来作为按钮的背景,这时候我们可以用Button类中的setBackgroundResource这个方法。而在背景图片中,我们可以做任何自己想做的事情,比如实现颜色渐变之类的,就像下面这个图片那样(normal.png)。
为此,我们先把上面的图片(normal.png)拷贝到项目的drawable-mdpi文件夹下,再修改CustomizeButtonActivity.java,这次我们用Button类中的setBackgroundResource方法:
public class CustomizeButtonActivity extends Activity
{
private Button smallButton;
private Button mediumButton;
private Button largeButton;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
smallButton = (Button)findViewById(R.id.samllbutton);
mediumButton = (Button)findViewById(R.id.mediumbutton);
largeButton = (Button)findViewById(R.id.largebutton);
// smallButton.setBackgroundColor(Color.YELLOW);
// mediumButton.setBackgroundColor(Color.YELLOW);
// largeButton.setBackgroundColor(Color.YELLOW);
smallButton.setBackgroundResource(R.drawable.normal);
mediumButton.setBackgroundResource(R.drawable.normal);
largeButton.setBackgroundResource(R.drawable.normal);
}
}
运行结果:
除small按钮状况良好外,其他两个按钮的样子令人难以忍受。怎么办呢?
解决办法就是将normal.png变成一个9-patch类型的png。那么,什么9-patch类型的png呢?patch在英文中的意思就是“补丁”的意思。对于9-patch,Android的官方文档是这样说的“The NinePatch class permitsdrawing a bitmap in nine sections. The four corners are unscaled; the four edges are scaled in one axis,and the middle is scaled in both axes.”意思就是,将一个bitmap分成9个部分,4个角不做缩放,4条边可以沿着某个坐标轴进行缩放,中间的部分则可沿着两个坐标轴进行缩放。但是,怎样才能做到这一点呢?方法就是用工具draw9patch将普通的png图片,编程9-patch类型的png。
其实9-patch也是标准的png格式的图片,只不过在图片中多了几条宽度为1个像素的几条黑线而已,通常我们可以使用Android SDK安装目录下的tools子目录中的draw9patch.bat这个工具,可以很轻松地将普通的png,变成9-patch类型的png。那好,我们现在就来将前面用到normal.png用这个工具,使其变成9-patch。
上面就是工具启动后的样子。将normal.png拖入其中,得到
左边是编辑区,右边是形状预览。现在我们就在左边画几条1个像素宽度的黑线,使之如下:
然后保存为nice,注意文件名的后缀必须是.9.png,也就是说上面保存后的文件名是nice.9.png。
选中Show patches,可以看到:
很显然,整个图片被分割成了9块,这也正是9-patch这个名称的由来。
需要特别说明的是,4条黑线的作用是有所不同的,上面那条黑线指定了水平方向可以缩放的范围,左边那条黑线指定了垂直方向可以缩放的范围,由此不难看出区域2和区域8在垂直方向缩放时,是不会变化的;区域4和区域6在水平方向缩放时,是不会变化的。区域1、3、7、9在垂直和水平方向缩放时,均不会变化。
右边的黑线指定了在垂直方向上可以包含内容(比如按钮上的文字)的范围,最下面的黑线指定了在水平方向上可以包含内容的范围。
所以左上两条黑线,指定的是缩放方面的范围,右下两条黑线指定的是可以显示内容的范围。很显然上图中左右两条黑线、上下两条黑线的长度一样,所以不宜辨别彼此之间的区别,关于这个问题等会再讲。下面先不放来看看用nice.9.png代贴normal.png的效果,为此,我们把nice.9.png拷贝到drawable-mdpi文件夹下,再修改CustomizeButtonActivity.java使之如下:
public class CustomizeButtonActivity extends Activity
{
private Button smallButton;
private Button mediumButton;
private Button largeButton;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
smallButton = (Button)findViewById(R.id.samllbutton);
mediumButton = (Button)findViewById(R.id.mediumbutton);
largeButton = (Button)findViewById(R.id.largebutton);
//// smallButton.setBackgroundColor(Color.YELLOW);
//// mediumButton.setBackgroundColor(Color.YELLOW);
//// largeButton.setBackgroundColor(Color.YELLOW);
//
// smallButton.setBackgroundResource(R.drawable.normal);
// mediumButton.setBackgroundResource(R.drawable.normal);
// largeButton.setBackgroundResource(R.drawable.normal);
smallButton.setBackgroundResource(R.drawable.nice);
mediumButton.setBackgroundResource(R.drawable.nice);
largeButton.setBackgroundResource(R.drawable.nice);
}
}
运行结果如下:
这次一切都很正常。
现在我们来看看比较特殊的情况。假定有如下图所示的按钮(normalong.png)
用工具draw9patch对其编辑如下:
我们看到左边有两个黑线段,它们指定了图形在垂直方向可以缩放的区域,最上面的线段指定的是在水平方向可以缩放的区域,原型图标坐在的区域,很显然属于非缩放区,因此不管图形的其他部分如何变化,这部分都是保持不变的。这样一来,图形实际上是被分割成了12块,而不是前面说的9块,它有两个可以缩放的区域(粉红色部分,这两部分可根据需要自动沿着水品或者垂直方向进行缩放)如下图:
下图中的阴影部分是可以显示内容的区域(比如文字):
从上面的讨论也可以看出前面提到的问题,即4条1像素的黑线的长度是可以彼此不一样的。
OK,将该图另存为nicelong.9.png,并将其拷贝到拷贝到drawable-mdpi文件夹下,再修改CustomizeButtonActivity.java使之如下:
public class CustomizeButtonActivity extends Activity
{
private Button smallButton;
private Button mediumButton;
private Button largeButton;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
smallButton = (Button)findViewById(R.id.samllbutton);
mediumButton = (Button)findViewById(R.id.mediumbutton);
largeButton = (Button)findViewById(R.id.largebutton);
////// smallButton.setBackgroundColor(Color.YELLOW);
////// mediumButton.setBackgroundColor(Color.YELLOW);
////// largeButton.setBackgroundColor(Color.YELLOW);
////
//// smallButton.setBackgroundResource(R.drawable.normal);
//// mediumButton.setBackgroundResource(R.drawable.normal);
//// largeButton.setBackgroundResource(R.drawable.normal);
//
// smallButton.setBackgroundResource(R.drawable.nice);
// mediumButton.setBackgroundResource(R.drawable.nice);
// largeButton.setBackgroundResource(R.drawable.nice);
smallButton.setBackgroundResource(R.drawable.nicelong);
mediumButton.setBackgroundResource(R.drawable.nicelong);
largeButton.setBackgroundResource(R.drawable.nicelong);
}
}
运行结果如下:
表现一切正常,圆形部分(不甚美观哈,不过这样的工作,其实可以交给美工方面的专业人士去处理)并没有随按钮的缩放而缩放。
参考资料:
1. Android SDK文档
2. http://www.anddev.org/tutorial_buttons_with_niceley_stretched_background-t4369.html
3. 关于按钮的三种状态问题,可以参考:
AndroidGUI04:Button(BasicButton,ImageButton, Check Box, Toggle Button, Radio Button)的常用技巧