六、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); } }13.使用原始资源:Android SDK会为位于/res/raw/目录下的资源在R类中生成一个索引项,在Java代码中可按R.raw.<file_name>的 语法格式来访问。 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文件,该文件中存放的就是字符串资源。
新闻热点
疑难解答