六、Android应用的资源:
1.有经验的开发者会专门定义一个或多个接口或类,然后在其中以常量的形式来定义程序中用的所有字符串、数值等,这些常量的名称十分明确,这样的方式可以很好地提高程序的可维护性和解耦性。2.assets目录下存放的资源代表应用无法直接访问的原生资源,应用程序需要通过AssetManager以二进制流的形式来读取资源。
3.Android应用资源的存储:
/res/anim/ 存放定义补间动画的XML文件。
/res/color/
/res/drawable/ 该目录下存放各种位图文件(如*.png、*.9.png、*.jpg、*.gif)等,以及能编译成各种Drawable对象的XML文件。
/res/layout/
/res/menu/ 存放为应用程序定义各种菜单的资源,包括选项菜单、子菜单、上下文菜单资源。
/res/raw/ 该目录下存放任意类型的原生资源,在java代码中可通过调用Resources对象的openRawResource(int id)方法来获取该资源的二进制输入流。*推荐把这些原生资源保存到/assets目录下。
/res/values/ 这些资源文件的根元素都是<resources.../>元素;styles.xml定义样式资源,style子元素代表添加一个样式。
/res/xml/ 任意的原生XML文件。这些XML文件可在Java代码中使用Resources.getXML()方法进行访问。
* 大部分程序,系统将会选择drawable-mdpi目录下的图片文件,如果系统使用高分屏,那么系统将会选择drawable-hdpi目录下的图片文件。
4.从drawable资源中加载图片,并设为该窗口的背景:
getWindow().setBackgroundDrawableResource(R.drawable.back);
从string资源中获取指定字符串资源,并设置该窗口的标题:
getWindow().setTitle(getResources().getText(R.string.main_title));
5.与定义字符串资源类似的是,Android也允许使用资源文件来定义boolean常量,<resources.../>根元素内通过<bool.../>子元素来定义boolean常量;
定义整型常量,<resources.../>根元素内通过<integer.../>子元素来定义整型常量;
6.Android允许通过资源文件来定义数组资源,采用arrays.xml文件来定义数组,<resources.../>根元素内可包含三种子元素:
<array.../>子元素:定义普通类型的数组。例如Drawable数组;
<string-array.../>子元素:定义字符串数组;
<integer-array.../>子元素:定义整数数组。
7.Drawable资源:
为了在程序中获得实际的Drawable对象,Resources提供了Drawable getDrawable(int id)方法。
图片资源:Android不允许图片资源的文件名中出现大写字母,且不能以数字开头,否则Android SDK无法为该图片在R类中生成资源索引。
StateListDrawable资源:用于组织多个Drawable对象,当使用StateListDrawable作为目标组件的背景、前景图片时,StateListDrawable对象所显示的Drawable对象会随目标组件状态的改变而自动切换。
根元素为<selector.../>,该元素可以包含多个<item.../>元素,android:state_xxx:指定一个特定状态,比如可以指定目标组件得到焦点、失去焦点时使用不同的颜色。
LayerDrawable资源:包含一个Drawable数组,系统将会按这些Drawable对象的数组顺序来绘制它们,索引最大的Drawable对象将会被绘制在最上面。
根元素为<layer-list.../>,该元素可以包含多个<item.../>元素。
ShapeDrawable资源:用于定义一个基本的几何图形(如矩形、圆形、线条等),例如作为文本框的background属性,则可以在Android应用中做出各种外观的文本框。
根元素是<shape.../>元素,可指定属性android:shape=["rectangle"|"oval"|"line"|"ring"]。
子元素可为:<corners.../>定义几何图形的四个角的弧度
<gradient.../>定义使用渐变色填充
<padding.../>定义几何形状的内边距
<size.../>定义几何形状的大小
<solid.../>定义使用单种颜色填充
<stroke.../>定义为几何形状绘制边框
ClipDrawable资源:代表从其他位图上截取的一个“图片片段”,使用<clip.../>元素。
android:clipOrientation:指定截取方向,可设置水平截取或垂直截取。
// 获取图片所显示的ClipDrawable对象
final ClipDrawable drawable = (ClipDrawable) imageView.getDrawable();
可调用setLevel(int level)方法来设置截取的区域大小,当level为0时,截取的图片片段为空;当level为10000时,截取整张图片。
AnimationDrawable资源(以补间动画为例):以<set.../>元素作为根元素,元素内可指定alpha、scale、translate、rotate这4个元素。
定义动画的XML资源应该放在/res/anmi路径下。
定义补间动画的思路:设置一张图片的开始状态(包括透明度、位置、缩放比、旋转度)、并设置该图片的结束状态(包括透明度、位置、缩放比、旋转度),
再设置动画的持续时间,Android系统会使用动画效果把这张图片从开始状态变换到结束状态。
fromXxx、toXxx属性:用于定义图片的开始状态、结束状态。
pivotX、pivotY属性:用于指定变换的“中心点”————比如进行旋转变换时,需要指定“旋轴点”;进行缩放变换时,需要指定“中心点”。
android:interpolator属性:该属性指定动画的变换速度,<set.../><alpha.../><scale.../><translate.../><rotate.../>都可以指定一个。
android:shareInterpolator="true"属性:让<set.../>元素下所有的变换效果使用相同的动画速度。
// 加载动画资源
final Animation anim = AnimationUtils.loadAnimation(Context ctx,R.anim.my_anim);
// 开始动画
imageView.startAnimation(anim);
// 设置动画结束后保留结束状态
anim.setFillAfter(true); // 也可以为<set.../>设置android:fillAfter为true来实现。
8.使用原始XML资源:
9.使用菜单(Menu)资源:Android推荐使用XML来定义菜单,使用XML定义菜单将会提供更好的解耦。
10.样式(Style)资源:根元素是<resources.../>,该元素内可包含多个<style.../>子元素,每个<style.../>元素定义一个样式。
<style.../>元素内可包含多个<item.../>子元素,每个<item.../>子元素定义一个格式项。
<style.../>元素指定如下两个属性:
name:指定样式的名称。
parent:指定该样式所继承的父样式。当继承某个父样式时,该样式将会获得父样式中定义的全部格式。
当前样式也可以覆盖父样式中指定的格式。
11.主题(Theme)资源:根元素是<resources.../>,使用<style.../>元素来定义主题,元素内可包含多个<item.../>子元素,每个<item.../>子元素定义一个格式项。
主题与样式的区别:
主题不能作用于单个的View组件,主题应该对整个应用中的所有Activity起作用,或对指定的Activity起作用。
主题定义的格式应该是改变窗口外观的格式,例如窗口标题、窗口边框等。
// 在代码中使用该主题
setTheme(android.R.style....);
Android中提供了几种内置的资源,这些主题通过查询Android.R.style类可以看到,比如对话框风格的窗口android:theme="@android:style/Theme.Dialog"。
Android主题同样支持继承,也可通过继承系统主题来实现自定义主题。
12.属性(Attribute)资源:用户开发的自定义View组件需要指定属性,需要使用属性资源。
根元素为<resources.../>,该元素里包含两个子元素;
attr子元素:定义一个属性。
declare-styleable子元素:定义一个styleable对象,每个styleable对象就是一组attr属性的集合。
使用属性文件定义了属性之后,就可以在自定义组件的构造器中通过AttributeSet对象来获取这些属性了。
至于到底在哪个View组件中使用该属性,属性资源所定义的属性可以返回什么作用,取决于自定义组件的代码实现。
在属性资源中定义<declare-styleable.../>元素时,也可在其内部直接使用<attr.../>定义属性,指定一个format属性即可,例如<attr name="duration" format="integer"/>。
属性位于"http://schemas.android.com/apk/res/项目子包"命名空间下。
例子:
public class AlphaImageView extends ImageView {
// 图像透明度每次改变的大小
private int alphaDelta = 0;
// 记录图片当前的透明度
private int curAlpha = 0;
// 每隔多少毫秒透明度改变一次
private final int SPEED = 300;
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;
}
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);
}
}
};
@Override
protected void onDraw(Canvas canvas) {
this.setAlpha();
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);
}
}
AssetManager提供了两个常用方法访问Assets资源:
InputStream open(String fileName):根据文件名来获取原始资源对应的输入流。
AssetsFileDescriptor openFd(String fileName):根据文件名来获取原始资源对应的AssetFileDescriptor。
AssetsFileDescriptor代表了一项原始资源的描述,应用程序可通过AssetFileDescriptor来获取原始资源。
举例:
MediaPlayer mediaPlayer1 = null;
MediaPlayer mediaPlayer2 = null;
.................
mediaPlayer1 = MediaPlayer.create(this, R.raw.bomb);
AssetManager am = getAssets();
try {
AssetsFileDescriptor afd = am.openFd("shot.mp3");
mediaPlayer2 = new MediaPlayer();
mediaPlayer2.setDataSource(afd.getFileDescriptor());
mediaPlayer2.prepare();
} catch (IOException e) {
e.printStackTrace();
}
14.资源国际化:Android本身采用了XML资源文件管理所有字符串消息,开发者需要为values目录添加几个不同的语言国家版本。
不同values文件的命名方式为:values-语言代码-r国家代码
在res\values-en-rUS、res\values-zh-rCN等目录下分别创建strings.xml文件,该文件中存放的就是字符串资源。