使用Drawable资源
使用原始XML资源
使用Menu资源
样式(Style)和主题(Theme)资源
属性(Attribute)资源
使用原始资源
使用Drawable资源
Drawable资源是Android应用中的使用最广泛的资源,也是Android应用中最灵活的资源,它不仅可以直接使用 *.png、 *.jpg、 *.gif、 *.9.png等图片作为资源,也可以使用多种XML文件作为资源。只要一份XML文件可以被系统编译成Drawable子类的对象,那么这份XML文件即可以作为Drawable资源。
Drawable资源通常保存在/res/drawable目录下,实际上可能保存在/res/drawable-ldpi、/res/drawable-mdpi、/res/drawable-hdpi目录下。
1.1 图片资源
图片资源是最简单的Drawable资源,只要把图片放入/res/drawable-xxx目录下,Android SDK就会在编译应用自动加载该图片,并在R资源清单类中生成该资源索引。
注意:Android不允许图片资源的文件名中出现大写字母,且不能以数字开头。否则Android SDK无法为该图片在R类中生成资源索引。
一旦系统在R资源清单类中生成了指定资源的索引,接下来就可以在Java类中使用如下语法格式来访问资源:
[<package>.]R.drawable.<file_name>
在XML代码中按如下格式来访问该资源:
@[<package_name>:]drawable/file_name
为了在程序中获得实际的Drawable对象,Resources提供了Drawable getDrawable(int id)方法,该方法即可根据Drawable资源在R清单中的ID来获取实际的Drawable对象。
1.2 StateListDrawable资源
StateListDrawable用于组织多个Drawable对象。当使用StateListDrawable作为目标组件的背景、前景图片时,StateListDrawable对象所显示的Drawable对象会随目标组件状态的改变而自动切换。
定义StateListDrawable对象的XML文件的根元素<selector…/> ,该元素可包含多个<item.../>元素,该元素可指定如下属性:
android:color或 android:drawable:指定颜色或drawable对象
android:state_xxx:指定一个特定状态。
my_image.xml
<?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="#111"/>
</selector>
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="fill_parent"
android:layout_height="fill_parent"
>
<!-- 使用StateListDrawable资源 -->
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@drawable/my_image"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@drawable/my_image"
/>
</LinearLayout>
1.3 LayerDrawable资源
与StateListDrawable有点类似,LayerDrawable也可以包含一个Drawable数组,因此系统将会按这些Drawable对象的数组顺序来绘制它们,索引最大的Drawable对象将会被绘制在最上面。
定义LayerDrawable对象的XML文件的根元素为<layer-list.../>,该元素可以包含多个<item.../>元素,该元素可指定如下属性:
android:drawable:指定作为LayerDrawable元素之一的Drawable对象。
android:id:为该Drawable对象指定一个标识。
android:buttom|top|button:它们用于指定一个长度值,用于指定将该Drawable对象绘制到目标组件的指定位置。
my_bar.xml
<?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>
layout_logo.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<bitmap android:src="@drawable/icon"
android:gravity="center" />
</item>
<item android:top="25dp" android:left="25dp">
<bitmap android:src="@drawable/icon"
android:gravity="center" />
</item>
<item android:top="50dp" android:left="50dp">
<bitmap android:src="@drawable/icon"
android:gravity="center" />
</item>
</layer-list>
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="fill_parent"
android:layout_height="fill_parent"
>
<!-- 定义一个拖动条,并改变轨道外观 -->
<SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progressDrawable="@drawable/my_bar"
style="@android:style/Widget.ProgressBar.Horizontal"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/layout_logo"
/>
</LinearLayout>
1.4 ShapeDrawable资源
ShapeDrawable用于定义一个基本的几何图形(如矩形、圆形、线条等),定义ShapeDrawable的XML文件的根元素是<shape.../>元素,该元素可指定如下属性:
android:shape=[“rectangle”|“Oval”|“line”|“ring”]:指定定义哪种类型的几何图形。
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="fill_parent"
android:layout_height="fill_parent"
>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_1"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_2"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/my_shape_3"
/>
</LinearLayout>
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>
1.5 ClipDrawable资源
ClipDrawable代表从其它位图上截取的一个“图片片段”。在XML文件中定义ClipDrawable对象使用<clip.../>元素。
可指定如下三个属性:
android:drawable:指定截取的源Drawable对象。
android:clipOrientation:指定截取方向,可设置水平截取或垂直截取。
android:gravity:指定截取时的对齐方式。
使用ClipDrawable对象可调用setLevel(int level)方法来设置截取的区域大小。当Level为0时,截取的图片片段为空,当Level为10000时,截取整张图片。
ClipDrawableTest.java
public class ClipDrawableTest 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);
}
}
my_clip.xml
<?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>
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="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/my_clip"
/>
</LinearLayout>
1.6 AnimationDrawable资源
AnimationDrawable代表一个动画。定义补间动画的XML资源文件以<set.../>元素作为根元素,该元素内可以指定如下4个元素:
alpha:设置透明度的改变
scale:设置图片进行缩放改变
translate:设置图片进行位移变换
rotate:设置图片进行旋转
定义动画的XML资源应该放在/res/anim路径下,当使用ADT创建一个Android应用时,默认不会包含该路径,开发者需要自行创建该路径。
除此之外,上面<set…/>、 <alpha…/>、 <scale…/>、 <rotate…/>都可以指定android:interpolator属性,该属性指定动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等。Android系统的R.anim类中包含大致常量,它们定义了不同的动画速度,例如:
linear_interpolator:匀速变换
accelerate_interpolator:加速变换
deceletate_interpolator:减速交换。
如果程序想让<set…/>元素下所有的变换效果使用相同的动画速度,则可指定android:shareInterpolator=“true”
在java代码中访问动画资源文件:[<package>.]R.anim.<file_name>
在XML文件中访问动画资源文件:@[<package_name>:]anim/file_name
AnimationDrawable.java
public class AnimationDrawable 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);
}
});
}
}
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="fill_parent"
android:layout_height="fill_parent"
>
<ImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/java"
/>
<Button
android:id="@+id/bn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始动画"
/>
</LinearLayout>
使用原始XML资源
Android应用有一些初始化的配置信息、应用相关的数据资源需要保存,一般推荐使用XML文件来保存它们,这种资源被称为原始XML资源。
2.1 定义原始XML资源
原始XML资源一般保存在/res/xml路径下,这个目录手动创建。一旦成功定义原始XML资源,在其他XML文件中使用的语法格式如下:
@[<package_name>:]xml.file_name
在JAVA代码中则通过如下语法格式来访问它:
[<package_name>.]R.xml.<file_name>
例:使用原始XML文件:
XmlResTest.java
public class XmlResTest extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取bn按钮,并为该按钮绑定事件监听器
Button bn = (Button)findViewById(R.id.bn);
bn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
//根据XML资源的ID获取解析该资源的解析器。
// XmlResourceParser是XmlPullParser的子类。
XmlResourceParser xrp = getResources().getXml(R.xml.books);
try
{
StringBuilder sb = new StringBuilder("");
//还没有到XML文档的结尾处
while (xrp.getEventType() != XmlResourceParser.END_DOCUMENT)
{
//如果遇到了开始标签
if(xrp.getEventType() == XmlResourceParser.START_TAG)
{
//获取该标签的标签名
String tagName = xrp.getName();
//如果遇到book标签
if(tagName.equals("book"))
{
//根据属性名来获取属性值
String bookName = xrp.getAttributeValue(null , "price");
sb.append("价格:");
sb.append(bookName);
//根据属性索引来获取属性值
String bookPrice = xrp.getAttributeValue(1);
sb.append(" 出版日期:");
sb.append(bookPrice);
sb.append(" 书名:");
//获取文本节点的值
sb.append(xrp.nextText());
}
sb.append("\n");
}
//获取解析器的下一个事件
xrp.next();
}
EditText show = (EditText)findViewById(R.id.show);
show.setText(sb.toString());
}
catch (XmlPullParserException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
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="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/bn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/parse"
/>
<EditText
android:id="@+id/show"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:cursorVisible="false"
/>
</LinearLayout>
Books.xml
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book price="99.0" 出版日期="2008年">疯狂Java讲义</book>
<book price="89.0" 出版日期="2009年">轻量级Java EE企业应用实战</book>
<book price="69.0" 出版日期="2009年">疯狂Ajax讲义</book>
</books>
使用Menu资源
前面我们介绍菜单的时候,是完全采用JAVA代码来实现的,实际上Android推荐使用XML来定义菜单,使用XML定义菜单将会提供更好的解耦。
3.1 定义菜单资源
菜单资源文件通常应该放在/res/menu目录下,菜单资源的根元素通常是<menu…/>元素, <menu…/>元素无须指定任何属性, <menu…/>元素内可包含如下子元素。<item…/>元素:定义菜单项。
<group…/>子元素:将多个<item…/>定义的菜单包装成一个菜单组。 <group…/>子元素用于控制整组菜单的行为,该元素可指定如下常属性。
checkableBehavior:指定该组菜单的选择行为。可指定为none, all和single三个值。
menuCategory:指定菜单优先级,有效值为container、system\secondary和alternative。
visible:指定该组菜单是否可见。
enable:指定该组菜单是否可用。
<item…/>元素用于定义一份菜单, <item…/>元素可包<menu…/>
元素,位于<item…/>元素内部的<menu…/>就代表了子菜单。
<item…/>元素可指定如下常属性:
android:id: 为菜单项指定一个唯一标识。
android:title: 指定菜单项的标题。
android:icon: 指定菜单项的图标。
android:alphabeticShortcut:为菜单项指定字符快捷键。
android:numericShortcut:为菜单项指定数字快捷键。
android:checkable :设置该菜单项是否可选。
android:checked:设置该期间项是否选中。
android:visible:设置该菜单项是否可见。
android:enable:设置该菜单项是否可用。
MenuResTest.java
public class MenuResTest extends Activity
{
private TextView txt;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
txt = (TextView) findViewById(R.id.txt);
// 为文本框注册上下文菜单
registerForContextMenu(txt);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflator = new MenuInflater(this);
//状态R.menu.context对应的菜单,并添加到menu中
inflator.inflate(R.menu.my_menu, menu);
return super.onCreateOptionsMenu(menu);
}
// 每次创建上下文菜单时都会触发该方法
@Override
public void onCreateContextMenu(ContextMenu menu, View source,
ContextMenu.ContextMenuInfo menuInfo)
{
MenuInflater inflator = new MenuInflater(this);
//状态R.menu.context对应的菜单,并添加到menu中
inflator.inflate(R.menu.context , menu);
menu.setHeaderIcon(R.drawable.tools);
menu.setHeaderTitle("请选择背景色");
}
// 上下文菜单中菜单项被单击时触发该方法。
@Override
public boolean onContextItemSelected(MenuItem mi)
{
switch (mi.getItemId())
{
case R.id.red:
mi.setChecked(true);
txt.setBackgroundColor(Color.RED);
break;
case R.id.green:
mi.setChecked(true);
txt.setBackgroundColor(Color.GREEN);
break;
case R.id.blue:
mi.setChecked(true);
txt.setBackgroundColor(Color.BLUE);
break;
}
return true;
}
@Override
// 菜单项被单击后的回调方法
public boolean onOptionsItemSelected(MenuItem mi)
{
//判断单击的是哪个菜单项,并针对性的作出响应。
switch (mi.getItemId())
{
case R.id.font_10:
txt.setTextSize(10 * 2);
break;
case R.id.font_12:
txt.setTextSize(12 * 2);
break;
case R.id.font_14:
txt.setTextSize(14 * 2);
break;
case R.id.font_16:
txt.setTextSize(16 * 2);
break;
case R.id.font_18:
txt.setTextSize(18 * 2);
break;
case R.id.red_font:
txt.setTextColor(Color.RED);
mi.setChecked(true);
break;
case R.id.green_font:
txt.setTextColor(Color.GREEN);
mi.setChecked(true);
break;
case R.id.blue_font:
txt.setTextColor(Color.BLUE);
mi.setChecked(true);
break;
case R.id.plain_item:
Toast toast = Toast.makeText(MenuResTest.this
, "您单击了普通菜单项" , Toast.LENGTH_SHORT);
toast.show();
break;
}
return true;
}
}
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="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="15pt"
android:text="@string/content"
/>
</LinearLayout>
my_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:icon="@drawable/font"
android:title="@string/font_size">
<menu>
<!-- 定义一组单选菜单项 -->
<group android:checkableBehavior="single" >
<!-- 定义多个菜单项 -->
<item
android:id="@+id/font_10"
android:title="@string/font_10"/>
<item
android:id="@+id/font_12"
android:title="@string/font_12"/>
<item
android:id="@+id/font_14"
android:title="@string/font_14"/>
<item
android:id="@+id/font_16"
android:title="@string/font_16"/>
<item
android:id="@+id/font_18"
android:title="@string/font_18"/>
</group>
</menu>
</item>
<!-- 定义一个普通菜单项 -->
<item
android:id="@+id/plain_item"
android:title="@string/plain_item">
</item>
<item
android:icon="@drawable/color"
android:title="@string/font_color">
<menu>
<!-- 定义一组允许复选的菜单项 -->
<group>
<!-- 定义3个菜单项 -->
<item
android:id="@+id/red_font"
android:title="@string/red_title"/>
<item
android:id="@+id/green_font"
android:title="@string/green_title"/>
<item
android:id="@+id/blue_font"
android:title="@string/blue_title"/>
</group>
</menu>
</item>
</menu>
context.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 定义一组单选菜单项目 -->
<group android:checkableBehavior="single">
<!-- 定义3个菜单项 -->
<item
android:id="@+id/red"
android:title="@string/red_title"
android:alphabeticShortcut="r"/>
<item
android:id="@+id/green"
android:title="@string/green_title"
android:alphabeticShortcut="g"/>
<item
android:id="@+id/blue"
android:title="@string/blue_title"
android:alphabeticShortcut="b"/>
</group>
</menu>
样式(Style)和主题(Theme)资源
4.1 样式(Style)资源
一个样式等于一组格式的组合,Android样式也包含一组格式,为一个组件设置使用某个样式时,该样式所包含的全部格式将会应用于该组件。
Android样式也包含/res/values目录下,样式资源文件的根元素是<resources…/>元素,该元素内可包含多个<style…/>子元素,每个<style…/>元素定义一个样式。 <style…/>有两个子元素。
name: 指定样式的名称
parent: 指定该样式所继承的父样式
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="fill_parent"
android:layout_height="fill_parent"
>
<!-- 指定使用style1的样式 -->
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/style1"
style="@style/style1"
/>
<!-- 指定使用style2的样式 -->
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/style2"
style="@style/style2"
/>
</LinearLayout>
my_style.xml
<?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>
<style name="CrazyTheme">
<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>
</resources>
4.2 主题资源
主题资源的XML文件通常也放在/res/values目录下,根元素也是<resource…/>,同样使用<style>来定义主题。
主题和样式的区别主要表现在:
主题不能作用于间个的view组件,主体应对整个应用中的所有Activity起作用,或对指定的Activity起作用。
主题定义的格式应该是改变窗口外观的格式,例如窗口标题、窗口边框等。
<style name="CrazyTheme">
<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>
在xml定义了主题资源,这时在java代码中使用主题,可以通过setTheme(R.style.name)进行设置主题。
大部分时候,在AndroidManifest.xml文件中对指定应用、指定Activity应用主题更加简单。
如果想让应用中全部窗口使用该主题,只要为<application…/>元素添加android:theme属性,属性值是一个主题的名字,如以下代码。
属性(Attribute)资源
属性资源文件也放在/res/values目录下,属性资源文件的根元素也是<resources…/>该元素包括如下两个子元素。
attr: 子元素:定义一个属性
declare-styleable子元素:定义一个styleable对象,每个styleable对象就是一组AttributeSet对象
attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 定义一个属性 -->
<attr name="duration">
</attr>
<!-- 定义一个styleable对象来组合多个属性 -->
<declare-styleable name="AlphaImageView">
<attr name="duration"/>
</declare-styleable>
</resources>
Main.xml
<?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.crazyit.res"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<!-- 使用自定义组件,并指定属性资源中定义的属性 -->
<com.boby.res.AlphaImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/ee"
crazyit:duration="60000"
/>
</LinearLayout>
AlphaImageView.java
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);
}
}
};
/**
* @param context
* @param attrs
*/
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.setAlpha(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);
}
}
使用原始资源
除了上面介绍的各种XML文件、图片文件之外,Android应用可能还需要用到大量其他类型的资源,比如声音资源等。实际上,类似声音文件及其他各种类型的文件,只要Android没有为之提供专门的支持,这种资源都被称为原始资源。Android的原始资源可以放在如下两个地方:
位于/res/raw目录下,Android SDK会处理该目录下的资源,会在R清单类中为该目录下的资源生成一个索引项。
位于/assets/目录下,该目录下的资源是更加彻底的原始资源,Android应用需要通过AssetManager来管理该目录下的原始资源。
AssetManager是一个专门管理/assets/目录下下原始资源的管理器类。 AssetManager提供了如下方法来访问Assets资源。
InputStream open(String fileName):根据文件名获取原始资源对应的输入流。
AssetFileDescriptor openFd(String fileName):通过文件名来获取原始资源对应的AssetFileDescriptor,通过它来获取原始资源。
RawResDemo.java
public class RawResDemo 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()
{
public void onClick(View arg0)
{
// 播放声音
mediaPlayer1.start();
}
});
// 获取第二个按钮,并为它绑定事件监听器
Button playAsset = (Button) findViewById(R.id.playAsset);
playAsset.setOnClickListener(new OnClickListener()
{
public void onClick(View arg0)
{
// 播放声音
mediaPlayer2.start();
}
});
}
}
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="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/playRaw"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/play_raw"
/>
<Button
android:id="@+id/playAsset"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/play_asset"
/>
</LinearLayout>