您的位置:首页 > 移动开发 > Android开发

【android_温故知新】android 应用的资源

2016-01-08 15:23 567 查看
概述

应用资源概述
资源的类型以及存储方式
android 应用资源的存储

使用资源
在 Java 代码中使用资源清单项

在 Java 代码中访问实际资源

在 XML 文件中使用资源

字符串颜色尺寸资源

字符串颜色尺寸资源表

颜色值的定义

定义字符串颜色尺寸资源文件
字符串资源文件

颜色资源文件

尺寸资源文件

使用字符串颜色尺寸资源

数组Array资源

使用 Drawabale 资源
图片资源
温馨提示

StateListDrawable 资源不同状态的Drawable
StateListDrawable 的 item 元素所支持的状态

实例高亮显示正在输入的文本框

LayerDrawable 资源
实例定制拖动条的外观

ShapeDrawable 资源
实例椭圆形渐变背景的文本框

ClipDrawable 资源
实例徐徐展开的风景

AnimationDrawable 资源

属性动画Property Animation资源
实例不断渐变的背景色

使用布局Layout资源

使用菜单Menu资源

样式Style和主题Theme资源
样式资源
温馨提示

主题资源
实例给所有窗口添加边框背景

属性Attribute资源
温馨提示

使用原始资源

国际化和资源自适应
为 android 应用提供国际化资源
温馨提示

概述

如果从物理存在形式来分,android 应用的源代码大致可分为如下三大类

界面布局文件:XML 文件,文件中每个标签都对应于相应的 View 标签。

Java 源文件:应用中的 Activity、Service、BroadcastReceiver、ContentProvider 四大组件都是采用 Java 代码来实现的。

资源文件:主要以各种 XML 文件为主,还可包括 * .png、* .jpg、* .gif 图片资源。



应用资源概述

android 应用资源可分为两大类

1. 无法通过 R 资源清单类访问的原生资源,保存在 assets 目录下。

2. 可通过 R 资源清单类访问的资源,保存在 res 目录下。

大部分时候提到 android 应用资源时,往往都是指位于 /res/ 目录下的应用资源,android SDK 会在编译该应用时在 R 类中为它们创建对应的索引项。

资源的类型以及存储方式

android 要求在 res 目录下用不同的子目录来保存不同的应用资源。

android 应用资源的存储

目 录存放的资源
/res/animator/存放定义属性动画的 XML 文件
/res/anim/存放定义补间动画的 XML 文件
/res/color/存放定义不同状态下颜色列表的 XML 文件
/res/drawable/存放各种位图文件(如 * .png、* .9.png、* .jpg、* .gif)等。除此之外,也可能是编译如下各种 Drawable 对象的 XML 文件:
1. BitmapDrawable 对象
2. NinePatchDrawable 对象
3. StateListDrawable 对象
4. ShapeDrawable 对象
5. AnimationDrawable 对象
6. Drawable 的其他各种子类的对象
/res/layout/存放各种用户界面的局部文件
/res/menu/存放为应用程序定义各种菜单的资源,包括选项菜单、子菜单、上下文菜单资源
/res/raw/存放任意类型的原生资源(比如音频文件、视频文件等)。在 Java 代码中可通过调用 Resources 对象的 openRawResource(int id)方法来获取该资源的二进制输入流。实际上,如果应用程序需要使用原生资源,也可把这些原生资源保存在/assets/目录下,然后在应用程序中使用 AssetManager 来访问这些资源
/res/values/存放各种简单值的 XML 文件。这些简单值包括字符串、整数值、颜色值、数组等。
这些资源文件的根元素都是< resources…/ > ,为该< resources…/ >元素添加不同的子元素则代表不同的资源,例如:
1. string/integer/bool 子元素:代表添加一个字符串值、整数值或 boolean 值
2. color 子元素:代表添加一个颜色值
3. array 子元素或 string-array、int-array 子元素:代表添加一个数组
4. style 子元素:代表添加一个样式
5. dimen:代表添加一个尺寸
由于各种简单值都可定义在/res/values/目录下的资源文件中,如果在同一份资源文件中定义各种值,势必会增加程序维护的难度。为此,android 建议使用不同的文件来存放不同类型的值,例如:
1. arrays.xml:定义数组资源
2. color.xml:定义颜色值资源
3. dimens:定义尺寸值资源
4. strings.xml:定义字符串资源
5. styles.xml:定义样式资源
/res/xml/存放任意的原生 XML 文件。这些 XML 文件可以在 Java 代码中使用 Resources.getXML()方法进行访问

使用资源

在 android 应用中使用资源可分为 Java 代码和 XML 文件中使用资源,其中 Java 代码用于为 android 应用定义四大组件,而 XML 文件则用于为 android 应用定义各种资源。

1. 在 Java 代码中使用资源清单项

由于 android SDK 会在编译应用时在 R 类中为/res/目录下所有资源创建索引项,因此在 Java 代码中访问资源主要通过 R 类来完成。其完整的语法格式为:

[< package_name >.]R.< resource_type >.< resource_name >


< package_name >指定 R 类所在包,实际上就是使用全限定类名。当然,如果在 Java 程序中导入 R 类所在包,就可以省略包名

< resource_type >R 类中代表不同资源类型的子类,例如 string 代表字符串资源。

< resource_name >指定资源的名称。该资源名称可能是无后缀的文件名(如图片资源),也可能是 XML 资源元素中由 android:name 属性所指定的名称。

例如如下代码片段:

// 从 drawable 资源中加载图片,并设为该窗口的背景
getWindow().setBackgroundDrawableResource(R.drawable.back);
// 从 string 资源中获取指定字符串资源,并设置该窗口的标题
getWindow().setTitle(getResources().getText(R.string.main_title));
// 获取指定的 TextView 组件,并设置该组件显示 string 资源中的指定字符串资源
TextView msg = (TextView)findViewById(R.id.msg);
msg.setText(R.string.hello_message);


2. 在 Java 代码中访问实际资源

R 资源清单类为所有的资源都定义了一个资源清单项,但这个清单项只是一个 int 类型的值,并不是实际的资源对象。在大部分情况下,android 应用的 API 允许直接使用 int 类型资源清单项代替应用资源。

但有些时候,程序也需要使用实际的 android 资源,为了通过资源清单项来获取实际资源,可以借助于 android 提供的 Resources 类。

Resources 主要提供了如下两类方法

1. getXxx(int id):根据资源清单 ID 来获取实际资源。

2. getAssets():获取访问/assets/目录下资源的 AssetManager 对象。

Resources 由 Context 调用 getResources()方法来获取。

下面的代码片段示范了如何通过 Resources 获取实际字符串资源。

// 直接调用 Activity 的 getResource()方法来获取 Resources 对象
Resources res = getResources();
// 获取字符串资源
String mainTitle = res.getText(R.string.main_title)
// 获取 Drawable 资源
Drawable log = res.getDrawable(R.drawable.log);
// 获取数组资源
int[] arr = res.getIntArray(R.array.books);


3. 在 XML 文件中使用资源

当定义 XML 资源文件时,其中的 XML 元素可能需要指定不同的值,这些值就可设置为已定义的资源项,在 XML 代码中使用资源的完整语法格式为:

[< package_name >:]< resource_type >/< resource_name >


上面语法格式中各成分的说明如下。

< package_name >指定资源类所在应用的包。如果所引用的资源和当前资源位于同一个包下,则< package_name >可以省略

< resource_type >:R 类中代表不同资源类型的子类。

< resource_name >:指定资源的名称。该资源名称可能是无后缀的文件名(如图片资源),也可能是 XML 资源元素中由 android:name 属性所指定的名称。

例如如下代码片段在一份文件中定义了两种资源:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="red">#ff00</color>
<string name="hello">Hello!</string>
</resources>


接下来与它位于同一包中的 XML 资源文件就可通过如下方式来使用资源:

<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/red"
android:text="@string/hello_world"/>


字符串、颜色、尺寸资源

字符串资源、颜色资源、尺寸资源,它们对应的 XML 文件都将位于/res/values/目录下,它们默认的文件名以及在 R 类中对应的内部类如表所示。

字符串、颜色、尺寸资源表

资源类型资源文件的默认名对应于 R 类中得内部类的名称
字符串资源/res/values/string.xmlR.string
颜色资源/res/values/colors.xmlR.color
尺寸资源/res/values/dimens.xmlR.dimen

颜色值的定义

android 中的颜色值是通过红(Red)、绿(Green)、蓝(Blue)三原色以及一个透明度(Alpha)值来表示的,颜色值总是以(#)开头,接下来就是 Alpha-Red-Green-Blue 的形式。其中 Alpha 值可以省略,如果省略了 Alpha 值,那么该颜色默认是完全不透明的。

android 颜色值支持常见的 4 种形式。

#RGB:分别指定红、绿、蓝三原色的值(只支持0~f这 16 级颜色)来代表颜色。

#ARGB:分别指定红、绿、蓝三原色的值(只支持0~f这 16 级颜色)及透明度(只支持0~f这 16 级透明度)来代表颜色。

#RRGGBB:分别指定红、绿、蓝三原色的值(只支持00~ff这 256 级颜色)来代表颜色。

#AARRGGBB:分别指定红、绿、蓝三原色的值(只支持00~ff这 256 级颜色)以及透明度(只支持00~ff这 256 级颜色)来代表颜色。

在上面 4 种形式中,A、R、G、B 都代表一个十六进制的数,其中 A 代表透明度,R 代表红色数值,G 代表绿色数值,B 代表蓝色数值。

定义字符串、颜色、尺寸资源文件

字符串资源文件

位于/res/values/目录下,字符串资源文件的根元素是< resources… >,该元素里每个< string…/ >子元素定义一个字符串常量,其中< string…/ >元素的 name 属性指定该常量的名称,< string…/ >元素开始标签和结束标签之间的内容代表字符串值,如下代码所示:

<!--定义一个字符串,名称为hello_world,字符串值为Hello world!-->
<string name="hello_world">Hello world!</string>


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">字符串、颜色、尺寸资源</string>
<string name="c1">F00</string>
<string name="c2">0F0</string>
<string name="c3">00F</string>
<string name="c4">0FF</string>
<string name="c5">F0F</string>
<string name="c6">FF0</string>
<string name="c7">07F</string>
<string name="c8">70F</string>
<string name="c9">F70</string>
</resources>


颜色资源文件

位于/res/values/目录下,颜色资源文件的根元素是< resource… >,该元素里每个< color…/ >子元素定义一个字符串常量,其中< color…/ >元素的 name 属性指定该颜色的名称,< color…/ >元素开始标签和结束标签之间的内容代表颜色值,如以下代码所示:

<!--定义一个颜色,名称为c1,颜色为红色-->
<color name="c1">#F00</color>


<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="c1">#F00</color>
<color name="c2">#0F0</color>
<color name="c3">#00F</color>
<color name="c4">#0FF</color>
<color name="c5">#F0F</color>
<color name="c6">#FF0</color>
<color name="c7">#07F</color>
<color name="c8">#70F</color>
<color name="c9">#F70</color>
</resources>


尺寸资源文件

位于/res/values/目录下,尺寸资源文件的根元素是< resource… >,该元素里每个< dimen…/ >子元素定义一个尺寸常量,其中< dimen…/ >元素的 name 属性指定该尺寸的名称,< dimen…/ >元素开始标签和结束标签之间的内容代表颜色值,如以下代码所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="spacing">8dp</dimen>
<!-- 定义GridView组件中每个单元格的宽度、高度 -->
<dimen name="cell_width">60dp</dimen>
<dimen name="cell_height">66dp</dimen>
<!-- 定义主程序的标题的字体大小 -->
<dimen name="title_font_size">18sp</dimen>
</resources>


使用字符串、颜色、尺寸资源

正如前面介绍的,在 XML 文件中使用资源按如下语法格式

@[< package_name >:]< resource_type >/< resource_name >


下面程序的界面布局中使用了大量前面定义的资源。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<!-- 使用字符串资源,尺寸资源 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:gravity="center"
android:textSize="@dimen/title_font_size"/>
<!-- 定义一个GridView组件,使用尺寸资源中定义的长度来指定水平间距、垂直间距 -->
<GridView
android:id="@+id/grid01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:horizontalSpacing="@dimen/spacing"
android:verticalSpacing="@dimen/spacing"
android:numColumns="3"
android:gravity="center">
</GridView>
</LinearLayout>


public class MainActivity extends Activity {
// 使用字符串资源
int[] textIds = new int[]
{
R.string.c1, R.string.c2, R.string.c3,
R.string.c4, R.string.c5, R.string.c6,
R.string.c7, R.string.c8, R.string.c9
};
// 使用颜色资源
int[] colorIds = new int[]
{
R.color.c1, R.color.c2, R.color.c3,
R.color.c4, R.color.c5, R.color.c6,
R.color.c7, R.color.c8, R.color.c9
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建一个BaseAdapter对象
BaseAdapter ba = new BaseAdapter() {
@Override
public int getCount() {
// 指定一共包含9个选项
return textIds.length;
}

@Override
public Object getItem(int position) {
// 返回指定位置的文本
return getResources().getText(textIds[position]);
}

@Override
public long getItemId(int position) {
return position;
}

// 重写该方法,该方法返回的View将作为GridView的每个格子
@Override
public View getView(int position
, View convertView, ViewGroup parent) {
TextView text = new TextView(MainActivity.this);
Resources res = MainActivity.this.getResources();
// 使用尺度资源来设置文本框的高度、宽度
text.setWidth((int) res.getDimension(R.dimen.cell_width));
text.setHeight((int) res.getDimension(R.dimen.cell_height));
// 使用字符串资源设置文本框的内容
text.setText(textIds[position]);
// 使用颜色资源来设置文本框的背景色
text.setBackgroundResource(colorIds[position]);
text.setTextSize(20);
text.setTextSize(getResources()
.getInteger(R.integer.font_size));
return text;
}
};
GridView grid = (GridView) findViewById(R.id.grid01);
// 为GridView设置Adapter
grid.setAdapter(ba);
}
}


与定义字符串资源类似的是,android 也允许使用资源文件来定义 boolean 常量。例如,在/res/values/目录下增加一个 bools.xml 文件,该文件的根元素也是< resources…/ >,根元素内通过< bool…/ >子元素来定义 boolean 常量

<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="is_male">true</bool>
<bool name="is_big">false</bool>
</resources>


Java 代码中按如下语法格式访问即可:

[< package_name >.]R.bool.bool_name


在 XML 文件按如下格式即可访问资源:

@[< package_name >:]bool/bool_name


例如,为了在 Java 代码中获取指定 boolean 变量的值,可通过如下代码来实现:

Resources res = getResources();
boolean is_male = res.getBoolean(R.bool.is_male);


与定义字符串资源类似的是,android 也允许使用资源文件来定义整型常量。例如,在/res/values/目录下增加一个 integer.xml 文件(文件名可以自由选择),该文件的根元素也是< resource…/ >,根元素内通过< integer…/ >子元素来定义整型常量

<resources>
<integer name="my_size">32</integer>
<integer name="book_numbers">12</integer>
<resources/>


Java 代码中按如下语法格式访问即可:

[< package_name >.]R.integer.integer_name


在 XML 文件中按如下格式即可访问资源:

@[< package_name >:]integer/integer_name


例如,为了在 Java 代码中获取指定 整型变量的值,可通过如下代码来实现:

Resources res = getResources();
int my_size = res.getInteger(R.integer.my_size);


数组(Array)资源

上面的程序在 Java 代码中定义了两个数组,android 并不推荐在 Java 代码中定义数组,因为 android 允许通过资源文件来定义数组资源。

android 采用位于/res/values 目录下的 arrays.xml 文件来定义数组资源,定义数组时 XML 资源文件的根元素也是< resources…/ >,该元素内可包含如下三种子元素

< arrary…/ >子元素:定义普通类型的数组,例如 Drawable 数组。

< string-array…/ >子元素:定义字符串数组。

< integer-array…/ >子元素:定义整型数组。

Java 程序中通过如下形式访问资源

[< package_name >.]R.array.array_name


在 XML 文件中则可通过如下形式进行访问

@[< package_name >:]arrary/array_name


为了能在 Java 程序中访问到实际数组,Resources 提供了如下方法。

String[] getStringArray(int id):根据资源文件中字符串数组资源的名称来获取实际的字符串数组。

int[] getIntArray(int id):根据资源文件中整型数组资源的名称来获取实际的整型数组。

TypedArray obtainTypedArray(int id):根据资源文件中普通数组资源的名称来获取实际的普通数组。

TypedArray 代表一个通用类型的数组,该类提供了 getXxx(int index)方法来获取指定索引处的数组元素。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义一个Drawable数组 -->
<array name="plain_arr">
<item>@color/c1</item>
<item>@color/c2</item>
<item>@color/c3</item>
<item>@color/c4</item>
<item>@color/c5</item>
<item>@color/c6</item>
<item>@color/c7</item>
<item>@color/c8</item>
<item>@color/c9</item>
</array>
<!-- 定义字符串数组 -->
<string-array name="string_arr">
<item>@string/c1</item>
<item>@string/c2</item>
<item>@string/c3</item>
<item>@string/c4</item>
<item>@string/c5</item>
<item>@string/c6</item>
<item>@string/c7</item>
<item>@string/c8</item>
<item>@string/c9</item>
</string-array>
<!-- 定义字符串数组 -->
<string-array name="books">
<item>疯狂Java讲义</item>
<item>疯狂Ajax讲义</item>
<item>疯狂Android讲义</item>
</string-array>
</resources>


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<!-- 使用字符串资源,尺度资源 -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:gravity="center"
android:textSize="@dimen/title_font_size"
/>
<!-- 定义一个GridView组件,使用尺度资源中定义的长度来指定水平间距、垂直间距 -->
<GridView
android:id="@+id/grid01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:horizontalSpacing="@dimen/spacing"
android:verticalSpacing="@dimen/spacing"
android:numColumns="3"
android:gravity="center">
</GridView>
<!-- 定义ListView组件,使用了数组资源 -->
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="@array/books"
/>
</LinearLayout>


public class MainActivity extends Activity {
// 获取系统定义的数组资源
String[] texts;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
texts = getResources().getStringArray(R.array.string_arr);
// 创建一个BaseAdapter对象
BaseAdapter ba = new BaseAdapter() {
@Override
public int getCount() {
// 指定一共包含9个选项
return texts.length;
}

@Override
public Object getItem(int position) {
// 返回指定位置的文本
return texts[position];
}

@Override
public long getItemId(int position) {
return position;
}

// 重写该方法,该方法返回的View将作为的GridView的每个格子
@Override
public View getView(int position
, View convertView, ViewGroup parent) {
TextView text = new TextView(MainActivity.this);
Resources res = MainActivity.this.getResources();
// 使用尺度资源来设置文本框的高度、宽度
text.setWidth((int) res.getDimension(R.dimen.cell_width));
text.setHeight((int) res.getDimension(R.dimen.cell_height));
// 使用字符串资源设置文本框的内容
text.setText(texts[position]);
TypedArray icons = res.obtainTypedArray(R.array.plain_arr);
// 使用颜色资源来设置文本框的背景色
text.setBackground(icons.getDrawable(position));
text.setTextSize(20);
return text;
}
};
GridView grid = (GridView) findViewById(R.id.grid01);
// 为GridView设置Adapter
grid.setAdapter(ba);
}
}


使用 Drawabale 资源

Drawable 资源是 android 资源是 android 应用中使用最广泛的资源,也是 android 应用最灵活的资源,它不仅可以直接使用.png、.9.png、.jpg、.gif 等图片作为资源,也可以使用多种 XML 文件作为资源。只要一份 XML 文件可被系统编译成 Drawable 子类的对象,那么这份 XML 文本即可作为 Drawable 资源。

Drawable 资源通常保存在/res/drawable 目录下,实际上可能保存在/res/drawable-ldpi、/res/drawable-mdpi、/res/drawable-hdpi、/res/drawable-xhdpi 目录下。

图片资源

图片资源是最简单的 Drawable 资源,只要把.png、.9.png、.jpg、.gif 等格式的图片放入/res/drawable-xxx 目录下,android SDK 就会在编译应用中自动加载该图片,并在 R 资源清单类中生成该资源的索引。

温馨提示

android 要求图片资源的文件名必须符合 Java 标识符的命名规则,否则 android SDK 无法为该图片在 R 类中生成资源索引。

Java 类中使用如下语法格式来访问该资源

[< package_name >.]R.drawable.< file_name >


在 XML 代码中则按如下语法格式来访问该资源

@[< package_name >:]drawable/file_name


为了在程序中获得实际的 Drawable 对象,Resources 提供了 Drawable getDrawable(int id)方法,该方法即可根据 Drawable 资源在 R 资源清单类中的 ID 来获取实际的 Drawable 对象。

StateListDrawable 资源(不同状态的Drawable)

StateListDrawable 用于组织多个 Drawable 对象。当使用 StateListDrawable 作为目标组件的背景、前景图片时,StateListDrawable 对象所显示的 Drawable 对象会随目标组件状态的改变而自动切换。

定义 StateListDrawable 对象的 XML 文件的根元素为< selector…/ >,该元素可以包含多个< item…/ >元素,该元素可指定如下属性。

1. android:color 或 android:drawable:指定颜色或 Drawable 对象。

2. android:state_xxx:指定一个特定状态。

例如如下语法格式:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!--指定特定状态下的颜色-->
<item android:drawable="@color/btn_pressed"
android:state_pressed="true" | "false"/>
</selector>


StateListDrawable 的< item…/ >元素所支持的状态

属性值含 义
android:state_active代表是否处于激活状态
android:state_checkable代表是否处于可勾选状态
android:state_checked代表是否处于已勾选状态
android:state_enable代表是否处于可用状态
android:state_first代表是否处于开始状态
android:state_focused代表是否处于已得到焦点状态
android:state_last代表是否处于结束状态
android:state_middle代表是否处于中间状态
android:state_pressed代表是否处于已被按下状态
android:state_selected代表是否处于已被选中状态
android:state_window_focused代表窗口是否处于已得到焦点状态

实例:高亮显示正在输入的文本框

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 指定获得焦点时的颜色 -->
<item android:state_focused="true"
android:color="#f44"/>
<!-- 指定失去焦点时的颜色 -->
<item android:state_focused="false"
android:color="#ccf"/>
</selector>


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 使用StateListDrawable资源 -->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@drawable/my_image"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@drawable/my_image"/>
</LinearLayout>


LayerDrawable 资源

定义 LayerDrawable 对象的 XML 文件的根元素< layer-list…/ >,该元素可以包含多个< item…/ >元素,该元素可指定如下属性。

1. android:drawable:指定作为 LayerDrawable 元素之一的 Drawable 对象。

2. android:id:为该 Drawable 对象指定一个标识。

3. android:buttom | top | left | width:它们用于指定一个长度值,用于指定将该 Drawable 对象绘制到目标组件的指定位置。

例如如下语法格式:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<!--指定一个 Drawable 元素-->
<item android:id="@+id/background"
android:drawable="@drawable/background"/>

</layer-list>


实例:定制拖动条的外观

使用 SeekBar 时可指定一个 android:progressDrawable 属性,该属性可改变 SeekBar 的外观,借助于 LayerDrawable 即可改变 SeekBar 的轨道、已完成部分的 Drawable 对象。

<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义轨道的背景 -->
<item android:id="@android:id/background"
android:drawable="@drawable/grow" />
<!-- 定义轨道上已完成部分的外观-->
<item android:id="@android:id/progress"
android:drawable="@drawable/ok" />
</layer-list>


该示例还定义了如下 LayerDrawable 对象。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:src="@drawable/ic_launcher"
android:gravity="center" />
</item>
<item android:top="25dp" android:left="25dp">
<bitmap android:src="@drawable/ic_launcher"
android:gravity="center" />
</item>
<item android:top="50dp" android:left="50dp">
<bitmap android:src="@drawable/ic_launcher"
android:gravity="center" />
</item>
</layer-list>


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 定义一个拖动条,并改变轨道外观 -->
<SeekBar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progressDrawable="@drawable/my_bar"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/layout_logo"/>
</LinearLayout>


ShapeDrawable 资源

ShapeDrawabale 用于定义一个基本的几何图形(如矩形、圆形、线条等),定义 ShapeDrawable 的 XML 文件的根元素是< shape…/ >元素,该元素可指定如下属性。

1. android:shape=[“rectangle” | “oval” | “line” | “ring”]:指定定义哪种类型的几何图形。

定义 ShapeDrawable 对象的完整语法格式如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape=["rectangle" | "oval" | "line" | "ring"] >
<!--定义几何图形的四个角的弧度-->
<corners
android:radius="integer"
android:topLeftRadius="integer"
android:topRightRadius="integer"
android:bottomLeftRadius="integer"
android:bottomRightRadius="integer" />
<!--定义使用渐变色填充-->
<gradient
android:angle="integer"
android:centerX="integer"
android:centerY="integer"
android:startColor="color"
android:centerColor="color"
android:endColor="color"
android:gradientRadius="integer"
android:type=["linear" | "radial" | "sweep"]
android:useLevel=["true" | "false"] />
<!--定义几何形状的内边距-->
<padding
android:left="integer"
android:top="integer"
android:right="integer"
android:bottom="integer" />
<!--定义几何形状的大小-->
<size
android:width="integer"
android:height="integer" />
<!--定义使用单种颜色填充-->
<solid
android:color="color" />
<!--定义为几何形状绘制边框-->
<stroke
android:width="integer"
android:color="color"
android:dashWidth="integer"
android:dashGap="integer" />
</shape>


属 性说 明
android:radius表示四个角的弧度
android:angle表示方向角度。当 angle=0 时,渐变色是从左向右。 然后逆时针方向转,当 angle=90 时为从下往上。必须是 45 的整数倍
android:centerX相对 X 的渐变位置
android:centerY相对 Y 的渐变位置
android:gradientRadius渐变颜色的半径,单位应该是像素点。 需要 android:type=”radial”
android:dashGap破折线(虚线)之间的空隙的宽度
android:dashWidth破折线(虚线)的宽度
android:usesLevel如果当做是 LevelListDrawable 使用时值为 true,否则为 false.

实例:椭圆形、渐变背景的文本框

程序清单:my_shape_1.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置填充颜色 -->
<solid android:color="#fff"/>
<!-- 设置四周的内边距 -->
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<!-- 设置边框 -->
<stroke android:width="3dip" android:color="#ff0" />
</shape>


程序清单:my_shape_2.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 定义填充渐变颜色 -->
<gradient
android:startColor="#FFFF0000"
android:endColor="#80FF00FF"
android:angle="45"/>
<!-- 设置内填充 -->
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<!-- 设置圆角矩形 -->
<corners android:radius="8dp" />
</shape>


程序清单:my_shape_3.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<!-- 定义填充渐变颜色 -->
<gradient
android:startColor="#ff0"
android:endColor="#00f"
android:angle="45"
android:type="sweep"/>
<!-- 设置内填充 -->
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<!-- 设置圆角矩形 -->
<corners android:radius="8dp" />
</shape>


程序清单:main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_1"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_2"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_3"
/>
</LinearLayout>


ClipDrawable 资源

ClipDrawable 代表从其他位图上截取一个 “图片片段”。在 XML 文件中定义 ClipDrawable 对象使用 < clip…/ >元素,该元素的语法为:

<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/fengjing"
android:clipOrientation=["horizontal" | "vertical"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" | "fill_vertical" | "center_horizontal" | "fill_horizontal" | "center" | "fill" | "clip_vertical" | "clip_horizontal"]>
</clip>


上面的语法格式中可指定如下三个属性。

android:drawable:指定截取的源 Drawable 对象。

android:clipOrientation:指定截取方向,可设置水平截取或垂直截取。

android:gravity:指定截取时的对齐方式。

使用 ClipDrawable 对象时可调用 setLevel(int level)方法来设置截取的区域大小,当 level 为 0 时,截取的图片片段为空;当 level 为 10000 时,截取整张图片。

实例:徐徐展开的风景

<?xml version="1.0" encoding="UTF-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/shuangta"
android:clipOrientation="horizontal"
android:gravity="center">
</clip>


public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView imageview = (ImageView) findViewById(R.id.image);
// 获取图片所显示的ClipDrawable对象
final ClipDrawable drawable = (ClipDrawable)
imageview.getDrawable();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 如果该消息是本程序所发送的
if (msg.what == 0x1233) {
// 修改ClipDrawable的level值
drawable.setLevel(drawable.getLevel() + 200);
}
}
};
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 0x1233;
// 发送消息,通知应用修改ClipDrawable对象的level值。
handler.sendMessage(msg);
// 取消定时器
if (drawable.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 300);
}
}


AnimationDrawable 资源

AnimationDrawable 代表一个动画。android 既支持传统的逐帧动画(类似电影方式,一张图片、一张图片地切换),也支持通过平移、变换计算出来的补间动画。

下面以补间动画为例来介绍如何定义 AnimationDrawable 资源,定义补间动画的 XML 资源文件以< set…/ >元素作为根元素,该元素内可以指定如下 4 个元素:

1. alpha:设置透明度的改变。

2. scale:设置图片进行缩放改变。

3. translate:设置图片进行位移变换。

4. rotate:设置图片进行旋转。

定义动画的 XML 资源应该放在/res/anim 路径下,当使用 ADT 创建一个 android 应用时,默认不会包含该路径,开发者需要自行创建该路径。

定义补间动画的思路很简单:设置一张图片的开始状态(包括透明度、位置、缩放比、旋转度)、并设置该图片的结束状态(包括透明度、位置、缩放比、旋转度),再设置动画的持续时间,android 系统会使用动画效果把这张图片从开始状态变换到结束状态。

设置补间动画的语法格式如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="持续时间"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"]>
<alpha
android:fromAlpha="float"
android:toAlpha="float"/>
<scale
android:fromXScale="float"
android:fromYScale="float"
android:pivotX="float"
android:pivotY="float"
android:toXScale="float"
android:toYScale="float"/>
<translate
android:fromXDelta="float"
android:fromYDelta="float"
android:toXDelta="float"
android:toYDelta="float"/>
<rotate
android:fromDegrees="float"
android:pivotX="float"
android:pivotY="float"
android:toDegrees="float"/>
</set>


上面语法格式中包含了大量的 fromXxx、toXxx 属性,这些属性就用于定义图片的开始状态、结束状态。除此之外,当进行缩放变换(scale)、旋转(rotate)变换时,还需要指定如下 pivotX、pivotY 两个属性,这两个属性用于指定变换的“中心点”—-比如进行旋转变换时,需要指定“旋轴点”;进行缩放变换时,需要指定“中心点”。

除此之外,上面< set…/ >、< alpha…/ >、< scale…/ >、< translate…/ >、< rotate…/ >都可指定一个 android:interpolator 属性,该属性指定动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等,android 系统的 R.anim 类中包含了大致常量,它们定义了不同的动画速度,例如:

linear_interpolator:匀速变换。

accelerate_interpolator:加速变换。

decelerate_interpolator:减速变换。

如果程序想让< set…/ >元素下所有的变换效果使用相同的动画速度,则可指定 android:shareInterpolator=”true”。

<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:duration="5000">
<!-- 定义缩放变换 -->
<scale android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="2000"/>
<!-- 定义位移变换 -->
<translate android:fromXDelta="10"
android:toXDelta="130"
android:fromYDelta="30"
android:toYDelta="-80"
android:duration="2000"/>
</set>


在 Java 代码中则按如下语法格式来访问它:

[< package >.]R.anim.< file_name >


在 XML 文件中按如下语法格式来访问它:

@[< package_name >:]anim/file_name


为了在 Java 代码中获取实际的 Animation 对象,则可调用 AnimationUtils 的如下方法:

loadAnimation(Context ctx,int resId)


public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView image = (ImageView) findViewById(R.id.image);
// 加载动画资源
final Animation anim = AnimationUtils.loadAnimation(this,
R.anim.my_anim);
// 设置动画结束后保留结束状态
anim.setFillAfter(true);  // ①
Button bn = (Button) findViewById(R.id.bn);
bn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// 开始动画
image.startAnimation(anim);
}
});
}
}


<?xml version="1.0" encoding="UTF-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator"
android:duration="5000">
<!-- 定义缩放变换 -->
<scale android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="true"
android:duration="2000"/>
<!-- 定义位移变换 -->
<translate android:fromXDelta="10"
android:toXDelta="130"
android:fromYDelta="30"
android:toYDelta="-80"
android:duration="2000"/>
</set>


X 轴向右为正,Y 轴向下为正

在这些属性里面还可以加上 % 和 p,例如:

1. android:fromXDelta=”100%”,表示自身的 100%,也就是从 View 自己的位置开始

2. android:toXDelta=”80%p”,表示父层 View 的 80%,是以它父层 View 为参照的

属性动画(Property Animation)资源

Animator 代表一个属性动画,但它只是一个抽象类,通常会使用它的子类:AnimatorSet、ValueAnimator、ObjectAnimator、TimeAnimator。定义属性动画的 XML 资源应该放在/res/animator 路径下,当使用 ADT 创建一个 android 应用时,默认不会包含该路径,开发者需要自行创建该路径。先介绍一下如何定义属性动画资源。

1. < set…/ >:它是一个父元素,用于包含其他< objectAnimator…/ >、< animator…/ >或< set…/ >子元素,该元素定义的资源代表 AnimatorSet 对象。

2. < objectAnimator…/ >:用于定义 ObjectAnimator 动画。

3. < animator…/ >:用于定义 ValueAnimator 动画。

定义属性动画的语法格式如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">

<objectAnimator
android:duration="int"
android:interpolator=""
android:propertyName="string"
android:repeatCount="int"
android:repeatMode=["restart" | "reverse"]
android:startOffset="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:valueType=["floatType" | "intType"]

<animator
android:duration="int"
android:interpolator=""
android:repeatCount="int"
android:repeatMode="int"
android:startOffset="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:valueType=["floatType" | "intType"]

<set>
...
</set>

</set>


实例:不断渐变的背景色

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="#FF8080"
android:valueTo="#8080FF"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:valueType="intType">
</objectAnimator>


public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout container = (LinearLayout)
findViewById(R.id.container);
// 添加MyAnimationView组件
container.addView(new MyAnimationView(this));
}

public class MyAnimationView extends View {
public MyAnimationView(Context context) {
super(context);
// 加载动画资源
ObjectAnimator colorAnim = (ObjectAnimator) AnimatorInflater
.loadAnimator(MainActivity.this, R.animator.color_anim);
colorAnim.setEvaluator(new ArgbEvaluator());
// 对该View本身应用属性动画
colorAnim.setTarget(this);
// 开始指定动画
colorAnim.start();
}
}
}


使用布局(Layout)资源

Layout 资源文件应放在/res/layout 目录下,Layout 资源文件的根元素通常是各种布局管理器,比如 LinearLayout、TableLayout、FrameLayout 等,接着在该布局管理器中定义各种 View 组件即可。

在 Java 代码中按如下语法格式来访问它:

[< package_name >.]R.layout.< file_name >


在 XML 文件中可通过如下语法格式来访问它:

@[< package_name >:]layout/file_name


使用菜单(Menu)资源

实际上 android 推荐使用 XML 资源文件来定义菜单,使用 XML 资源文件定义菜单将会提供更好地解耦。

android 菜单资源文件放在/res/menu 目录下,菜单资源的根元素通常是< menu…/ >元素,< menu…/ >元素无须指定任何属性。

在 Java 代码中则按如下语法格式来访问它:

[< package_name >.]R.menu.< file_name >


在 XML 文件中可通过如下语法格式访问:

@[< package_name >:]menu/file_name


样式(Style)和主题(Theme)资源

样式资源

如果我们经常需要对某个类型的组件指定大致相似的格式,比如字体、颜色、背景色等,如果每次都要为 View 组件重复指定这些属性,无疑会有大量的工作量,而且不利于项目后期的维护。

温馨提示

android 样式包含一组格式,为一个组件设置使用某个样式时,该样式所包含的全部格式将会应用于该组件。一个样式相当于多个格式的集合,其他 UI 组件通过 style 属性来指定样式,这就相当于把该样式包含的所有格式同时应用于该 UI 组件。

android 的样式资源文件也放在 /res/values 目录下,样式资源文件的根元素是 < resources…/ >元素,该元素内可包含多个< style…/ >子元素,每个< style…/ >元素定义一个样式。< style…/ >元素指定如下两个属性。

1. name:指定样式的名称。

2. parent:指定该样式所继承的父样式。当继承某个父样式时,该样式将会获得父样式中定义的全部格式。当然,当前样式也可以覆盖样式中指定的格式。

<?xml version="1.0" encoding="UTF-8"?>
<resources>
<!-- 定义一个样式,指定字体大小、字体颜色 -->
<style name="style1">
<item name="android:textSize">20sp</item>
<item name="android:textColor">#00d</item>
</style>
<!-- 定义一个样式,继承前一个颜色 -->
<style name="style2" parent="@style/style1">
<item name="android:background">#ee6</item>
<item name="android:padding">8dp</item>
<!-- 覆盖父样式中指定的属性 -->
<item name="android:textColor">#000</item>
</style>
</resources>


在 XML 资源中按如下语法格式来使用样式:

@[< package_name >:]style/file_name


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 指定使用style1的样式 -->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/style1"
style="@style/style1"/>
<!-- 指定使用style2的样式 -->
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/style2"
style="@style/style2"/>
</LinearLayout>


主题资源

主题资源的 XML 文件通常也放在 /res/values 目录下,主题资源的 XML 文档同样以 < resource…/ >元素作为根元素,同样使用< style…/ >元素来定义主题。

主题与样式的区别主要体现在:

1. 主题不能作用于单个的 View 组件,主题应该对整个应用中的所有 Activity 起作用,或对指定的 Activity 起作用。

2. 主题定义的格式应该是改变窗口外观的格式,例如窗口标题、窗口边框等。

实例:给所有窗口添加边框、背景

<style name="YongTheme">
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">true</item>
<item name="android:windowFrame">@drawable/window_border</item>
<item name="android:windowBackground">@drawable/star</item>
</style>


上面主题定义中使用了两个 Drawable 资源,其中 @drawable/star 是一张图片,@drawable/window_border 是一个 ShapeDrawable 资源,该资源对应的 XML 文件代码如下。

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<!-- 设置填充颜色 -->
<solid android:color="#0fff"/>
<!-- 设置四周的内边距 -->
<padding android:left="7dp"
android:top="7dp"
android:right="7dp"
android:bottom="7dp" />
<!-- 设置边框 -->
<stroke android:width="10dip" android:color="#f00" />
</shape>


定义了上面主题之后,接下来即可在 Java 代码中使用该主题,例如如下代码:

public class MainActivity extends Activity {

public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setTheme(R.style.YongTheme);
//      setContentView(R.layout.main);
}
}


大部分时候,在 AndroidManifest.xml 文件中对指定应用、指定 Activity 应用主题更加简单。如果我们想让应用中全部窗口使用该主题,只要为< application…/ >元素添加 android:theme 属性。属性值是一个主题的名字,如以下代码所示:

< application android:theme="@style/YongTheme">
...
</application>


如果只是想让程序中某个 Activity 拥有这个主题,那么你可以修改< activity…/ >元素,同样通过 android:theme 指定主题即可。

android 中提供了几种内置的主题资源,这些主题通过查询 Android.R.style 类可以看到。例如前面介绍的对话框风格的窗口,我们只要采用如下代码来定义某个 Activity 即可。

<activity android:theme="@android:style/Theme.Dialog">
...
</activity>


与样式类似的是,android 主题同样支持继承,如果开发过程中还想利用某个主题,但需要对它进行局部修改,则可通过继承系统主题来实现自定义主题。例如如下代码片段:

<style name="YongTheme" parent="@android:style/Theme.Dialog">
...
</activity>


上面定义的 CrazyTheme 主题继承了 android.R.style.Theme.Dialog 主题,那么接下来在该< style…/ >元素中添加的< item…/ >子元素就可覆盖系统主题的部分属性了。

属性(Attribute)资源

如果用户的自定义 View 组件需要指定属性,就需要属性资源的帮助了。

属性资源文件也放在/res/values 目录下,属性资源文件的根元素也是< resources…/ >,该元素里包含如下两个子元素。

1. attr 子元素:定义一个属性。

2. declare-styleable 子元素:定义一个 styleable 对象,每个 styleable 对象就是一组 attr 属性的集合。

当我们使用属性文件定义了属性之后,接下来就可以在自定义组件的构造器中通过 AttributeSet 对象来获取这些属性了。

例如我们想开发一个默认带动画效果的图片,该图片显示时,自动从全透明变到完全不透明,为此我们需要开发一个自定义组件,但这个自定义组件需要制定一个额外 duration 属性,该属性控制动画的持续时间。

为了在自定义组件中使用 duration 属性,需要先定义如下属性资源文件。

<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义一个属性 -->
<attr name="duration">
</attr>
<!-- 定义一个styleable 对象来组合多个属性 -->
<declare-styleable name="AlphaImageView">
<attr name="duration"/>
</declare-styleable>
</resources>


上面的属性资源文件定义了该属性之后,至于到底在哪个 View 组件中使用该属性,该属性到底发挥什么作用,就不归属性资源文件管了。属性资源所定义的属性到底可以发挥什么作用,取决于自定义组件的代码实现。

例如如下自定义的 AlphaImageView,它获取了定义该组件所指定的 duration 属性之后,根据该属性来控制图片的透明度的改变。

温馨提示

在属性资源中定义< declare-styleable…/ >元素时,也可在其内部直接使用< attr…/ >定义属性,使用< attr…/ >时指定一个 format 属性即可,例如上面我们可以指定< attr name=”duratation” format=”integer”/>

public class AlphaImageView extends ImageView {
// 图像透明度每次改变的大小
private int alphaDelta = 0;
// 记录图片当前的透明度。
private int curAlpha = 0;
// 每隔多少毫秒透明度改变一次
private final int SPEED = 300;
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
// 每次增加curAlpha的值
curAlpha += alphaDelta;
if (curAlpha > 255) curAlpha = 255;
// 修改该ImageView的透明度
AlphaImageView.this.setAlpha(curAlpha);
}
}
};

public AlphaImageView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.AlphaImageView);
// 获取duration参数
int duration = typedArray
.getInt(R.styleable.AlphaImageView_duration, 0);
// 计算图像透明度每次改变的大小
alphaDelta = 255 * SPEED / duration;
}

@Override
protected void onDraw(Canvas canvas) {
this.setImageAlpha(curAlpha);
super.onDraw(canvas);
final Timer timer = new Timer();
// 按固定间隔发送消息,通知系统改变图片的透明度
timer.schedule(new TimerTask() {
@Override
public void run() {
Message msg = new Message();
msg.what = 0x123;
if (curAlpha >= 255) {
timer.cancel();
} else {
handler.sendMessage(msg);
}
}
}, 0, SPEED);
}
}


上面的程序中粗体字代码用于获取定义 AlphaImageView 时指定的 duration 属性,并根据该属性计算图片的透明度的变化幅度,接着程序重写了 ImageView 的 onDraw(Canvas canvas)方法,该方法启动了一个任务调度来控制图片透明度的改变。

上面的粗体字代码中得 R.styleable.AlphaImageView、R.styleable.AlphaImageView_duration 都是 Android SDK 根据属性资源文件自动生成的。

接着在界面布局文件使用 AlphaImageView 时可以为它指定一个 duration 属性,注意该属性位于“http://schemas.anroid.com/apk/res/ + 项目子包”命名空间下,例如本应用的包名为 org.yonga.res,那么 duration 属性就位于“http://schemas.anroid.com/apk/res/org.yonga.res”,也可以使用编辑器自动生成的命名空间。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:crazyit="http://schemas.android.com/apk/res/org.yonga.res"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 使用自定义组件,并指定属性资源中定义的属性 -->
<org.crazyit.res.AlphaImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="@drawable/javaee"
yonga:duration="60000"/>
</LinearLayout>


使用原始资源

类似声音文件及其各种类型的文件,只要 android 没有为之提供专门的支持,这种资源都被称为原始资源。android 的原始资源可以放在如下两个地方。

1. 位于/res/raw 目录下,Android SDK 会处理该目录下原始资源,Android SDK 会在 R 清单类中为该目录下的资源生成一个索引项。

2. 位于/assets/目录下,该目录下的资源是更彻底的原始资源。android 应用需要通过 AssetManager 来管理该目录下的原始资源。

Android SDK 会为位于/res/raw/目录下的资源在 R 类中生成一个索引项,

在 Java 代码中则按如下语法格式来访问它:

[< package_name >.]R.raw.< file_name >


在 XML 文件中可通过如下语法格式来访问它:

@[< package_name >:]raw/file_name


通过上面的索引项,android 应用就可以非常方便地访问/res/raw 目录下的原始资源,至于获取原始资源之后如何处理,则完全取决于实际项目的需要。

AssetManager 是一个专门管理/assets/目录下原始资源的管理器类,AssetManager 提供了如下两个常用方法来访问 Assets 资源。

1. InputStream open(String fileName):根据文件名来获取原始资源对应的输入流。

2. AssetFileDescriptor openFd(String fileName):根据文件名来获取原始资源对应的 AssetFileDescriptor。AssetFileDescriptor 代表了一项原始资源的描述,应用程序可通过 AssetFileDescriptor 来获取原始资源。

先在应用的/res/raw/目录下放入一个 bomb.mp3 文件—-Android SDK 会自动处理该目录下的资源,会在 R 清单类中为它生成一个索引项:R.raw.bomb。

接下来我们再往/assets/目录下放入一个 shot.mp3 文件—-需要通过 AssetManager 进行管理。

public class MainActivity extends Activity {
MediaPlayer mediaPlayer1 = null;
MediaPlayer mediaPlayer2 = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 直接根据声音文件的ID来创建MediaPlayer
mediaPlayer1 = MediaPlayer.create(this, R.raw.bomb);
// 获取该应用的AssetManager
AssetManager am = getAssets();
try {
// 获取指定文件对应的AssetFileDescriptor
AssetFileDescriptor afd = am.openFd("shot.mp3");
mediaPlayer2 = new MediaPlayer();
// 使用MediaPlayer加载指定的声音文件
mediaPlayer2.setDataSource(afd.getFileDescriptor());
mediaPlayer2.prepare();
} catch (IOException e) {
e.printStackTrace();
}
// 获取第一个按钮,并为它绑定事件监听器
Button playRaw = (Button) findViewById(R.id.playRaw);
playRaw.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// 播放声音
mediaPlayer1.start();
}
});
// 获取第二个按钮,并为它绑定事件监听器
Button playAsset = (Button) findViewById(R.id.playAsset);
playAsset.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// 播放声音
mediaPlayer2.start();
}
});
}
}


国际化和资源自适应

为 android 应用提供国际化资源

android 应用使用 res/values 目录下的资源文件来保存程序中用到的字符串消息,为了给这些消息提供不同语言、国家的版本,开发者需要为 values 目录添加几个不同的语言国家版本。不同 values 文件夹的命名方式为:

values-语言代码-r 国家代码


例如希望下面的应用支持简体中文、美式英文两种环境,则需要在 res 目录下添加 values-zh-rCN、values-en-rUS 两个目录。

如果希望应用程序的图片也能随语言、国家环境改变,那么还需要为 drawable 目录添加几个不同的语言国家版本。不同 drawable 文件夹的命名方式为:

drawable-语言代码-r 国家代码


温馨提示

如果还需要为 drawable 目录按分辨率提供文件夹,则可以在后面追加分辨率后缀,例如 drawable-zh-rCN-mdpi、drawable-zh-rCN-hdpi、drawable-zh-rCN-xhdpi、drawable-en-rUS-mdpi、drawable-en-rUS-hdpi、drawable-en-rUS-xhdpi 等。

下面的程序分别为 values 目录、drawable 目录创建了简体中文、美式英文两个版本。

在 res/drawable-zh-rCN-mdpi、res/drawabl-en-rUS-mdpi 目录下分别添加 logo.png 图片,这两个图片并不相同,一个是简体中文环境的图片,一个是美式英语环境的图片。

在 res/values-en-rUS、res/values-zh-rCN 目录下分别创建 string.xml 文件。

res/values-en-rUS 目录下的 string.xml 文件内容如下:

<resources>
<string name="ok">OK</string>
<string name="cancel">Cancel</string>
<string name="msg">Hello , Android!</string>
</resources>


res/values-zh-rCN 目录下的 string.xml 文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ok">确定</string>
<string name="cancel">取消</string>
<string name="msg">你好啊,可爱的小机器人!</string>
</resources>


如果 android 是简体中文的环境,就加载 res/values-zh-rCN/strings.xml 文件中得字符串资源、加载 res/drawable-zh-rCN 目录下的 Drawable 资源;如果是美式英语的环境,就加载 res/values-en-rUS/strings.xml 文件中得字符串资源、加载 res/drawable-en-rUS 目录下的 Drawable 资源。

在 Java 代码中编码时,程序根据资源 ID 设置字符串内容,而不是以硬编码的方式设置为固定的字符串内容。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android java xml 资源