1 Android应用资源简介
Android应用程序主要由两部分内容组成:代码和资源。资源主要就是指那些与UI相关的东西,例如UI布局、字符串和图片等。代码和资源分开可以使得应用程序在运行时根据实际需要来组织UI。这样就可使得应用程序只需要编译一次,就可以支持不同的UI布局。这种特性使得应用程序在运行时可以适应不同的屏幕大小和密度, 以及不同的国家和语言等。
2 Android应用程序资源的分类
Android应用程序资源主要分为两大类,分别是assets和res。
2.1 assets类资源
assets类资源放在工程根目录的assets子目录下,它里面保存的是一些原始的文件,可以以任何方式来进行组织。这些文件最终会被原装不动地打包在 apk文件中。如果我们要在程序中访问这些文件,那么就需要指定文件名来访问。假设在assets目录下有一个名称为filename的文件,那么就可以使用以下代码来访问它:
AssetManager am= getAssets();
InputStream is = assset.open("filename");
2.2 res类资源
res类资源放在工程根目录的res子目录下,它里面保存的文件大多数都会被编译,并且都会被赋予资源ID。这样我们就可以在程序中通过ID来访问res类的资源。res类资源按照不同的用途可以进一步划分为以下9种子类型,分别如下:
@1 animator以XML文件保存在res/animator目录下,用来描述属性动画。
属性动画通过改变对象的属性来实现动画效果,可以通过不断地修改对象的坐标值来实现对象移动动画,也可以不断地修改对象的Alpha通道值来实现对象的渐变效果。
@2 anim资源以XML文件保存在res/anim目录下,用来描述补间动画。
补间动画和属性动画不同,它是在对象的原来形状或者位置的基础上实现一个变换来得到的,可以对对象施加一个旋转变换,就可以获得一个旋转动画,也可以对对象实施一个缩放变换,就可以获得一个缩放动画。从数学上来讲,就是在对象的原来形状或者位置的基础上施加一个变换矩阵来实现动画效果。
注意:动画执行中,对象的属性是始终保持不变的,我们看到的只不过是它的一个变形副本。
@3 color资源以 XML文件保存在res/color目录下,用描述对象颜色状态选择器。我们可以定义一个选择器,规定一个对象在不同状态下显示不同的颜色。对象的状态可以划分为pressed、focused、selected、checkable、checked、enabled和window_focused等7种。
@4 drawable资源以XML或者Bitmap文件保存在res/drawable目录下,用来描述可绘制对象。例如,我们可以在里面放置一些图片(.png, .9.png, .jpg, .gif)来作为程序界面视图的背景图。
注意:保存在这个目录中的Bitmap文件在打包的过程中,可能会被优化的。例如,一个不需要多于256色的真彩色PNG文件可能会被转换成一个只有8位调色板的PNG面板,这样就可以无损地压缩图片,以减少图片所占用的内存资源。
除此之外也可能是编译成如下各种Drawable对象的XML文件:
- BitmapDrawable对象
- NinePatchDrawable对象
- StateListDrawable对象
- ShapeDrawable对象
- Animation对象
- Drawable的其他个种子类对象
@5 layout资源以XML文件保存在res/layout目录下,用来描述应用程序界面布局。
@6 menu资源以XML文件保存在res/menu目录下,用来描述应用程序菜单。例如,Options Menu、Context Menu和Sub Menu。
@7 raw资源以任意格式的文件保存在res/raw目录下,它们和assets类资源一样,都是原装不动地打包在apk文件中的,但它们会被赋予资源ID,这样我们就可以在程序中通过ID来访问它们。假设在res/raw目录下有一名为filename的文件,并且它在编译的过程,被赋予ID为R.raw.filename,那么就可使用以下代码来访问它:
Resources res = getResources();
InputStream is = res.openRawResource(R.raw.filename);
@8 values 这类资源以XML文件保存在res/values目录下, 一般来说分为六种值,分别保存在以下文件中,如下所示:
- arrays.xml (string-array,int-array) 定义数组资源
- colors.xml 定义颜色资源
- dimens.xml 定义尺寸资源
- strings.xml (integer,bool)定义字符串资源
- styles.xml 定义样式资源
@9 xml 这类资源以XML文件保存在res/xml目录下,一般就是用来描述应用程序的配置信息。
3 资源使用(颜色、字符串、尺寸、数组、资源国际化、layout、menu、自适应不同屏幕资源)
3.1 颜色资源(/res/values目录)
颜色XML文件格式代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources> //resources根元素
<color name="black" >#000000</color>
//color子元素
</resouces>
颜色定义格式说明:
- #RGB: R、G、B分别指红绿蓝三原色的值(支持0-f这16个级别)
- #ARGB: A指透明度,R、G、B分别指红绿蓝三原色的值(支持0-f这16个级别)
- #RRGGBB: R、G、B分别指红绿蓝三原色的值(支持0-ff这256个级别)
- #ARRGGBB: A指透明度,R、G、B分别指红绿蓝三原色的值(支持0-ff这256个级别)
引用格式:
- java代码中:R.color.color_name (这是一个int型的数据,用于表示资源的地址)
- XML文件中: @color/color_name
获得颜色值的方法
getResources().getColor();//返回一个类似#0000FF格式的颜色值
3.2 字符串资源(/res/values目录)
XML文件格式代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="here" >StringHere</string>
</resouces>
引用格式:
- java代码中: R.string.string_name
- XML文件中: @string/string_name
获得字符串的方法:
Resources.getString(int); //返回一个String类型的对象
注意:在控件中setText(int resid)和setText(String string_name)这两个方法都是允许的
3.3 尺寸资源(/res/values目录)
XML文件代码如下:
<dimen name="dimen_name">18dp</dimen>
说明:尺寸值的单位可以是px(像素)或者mm(毫米,实际屏幕尺寸)或dp
引用格式:
- java代码: R.dimen.dimen_name
- XML文件中: @dimen/dimen_name
获取尺寸资源方法:
Resources.getDimension(R.dimen.dimen_name);//返回一个float类型的对象
注意:该方法返回值为float类型,而setWidth()参数要求是int类型的,所以需要强制类型转换。
3.4 数组资源(/res/values目录)
3.4.1 数组资源基础
创建数组资源,在values目录下创建arrays.xml文件,然后在在arrays.xml中使用<string-array>或者<integer-array>标签定义数组,xml配置如下所示:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="languages">
<item>cxx</item>
<item>java </item>
<item>php</item>
<item>xml</item>
<item>html</item>
</string-array>
<integer-array name="reminder_methods_values" translatable="false">
<item>1</item>
<item>2</item>
<item>3</item>
</integer-array>
</resources>
其中:<array>是普通数组,<string-array>定义的是字符数组,<integer-array>是整数数组。
3.4.2 引用数组资源
引用数组资源的方式有两种,代码中引用和xml文件中引用,分别如下:
@1 在java代码中引用
Resources res =getResources();
String[] languages = res.getStringArray(R.array.languages);
String[] reminder_methods = res.getIntArray(R.array.reminder_methods_values);
另外,还可以通过obtainTypedArray(int ResId)该防范获得一个 TypedArray类型的普通数组,该类提供了getXXX(int index)方法来获取指定索引处的数组元素。
@2 在xml中引用(这里以spinner控件为例,因为spinner的entries属性刚好需要数组资源)
<Spinner
android:id="@+id/spinner1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/languages"
/>
注意:上面引用的时候是@array。
3.5 资源国际化(/res/drawable-zh-rCN-hdpi目录 & /res/values-语言代码-r-国家代码目录)
@1 字符串国际化:只要在res文件夹下新建对应语言的values文件夹就可以。
Android国际化
使用XML资源文件来管理所有字符串消息。不同values文件夹命名方式为:values-语言代码-r-国家代码,例如values-zh-rCN,values-en-rUS
注意:新建Android项目时,会在res目录下自动创建一个默认语言环境的文件夹values。当某一个资源没有在语言环境的对应的资源集合中找到时,就会使用values下的资源。 若某一个语言环境没有在项目中定义语言环境,那么也会使用values下的资源,是使用XML文件进行资源配置。
@2 图片国际化
在res下新建drawable-zh文件夹,存放中文环境下的图片,再新建 drawable-en 作为英语环境下的图片。关于图片名称解读如下:
在新建Android项目时,会在res目录下自动创建三个默认语言环境的文件夹:drawable-hdpi | drawable-ldpi | drawable-mdpi 分别用于存放高、中、低分辨率的图片。Android 系统会根据手机的分辨率自动从不同的对应的某一个文件夹下去加载图片。 同样,它们也可以国际化,命名规则为:drawable-语言代码-r-国家代码-分辨率,比如:drawable-zh-rCN-hdpi 或 drawable-en-rUS-mdpi。使用方式如下:
- 在XML文件中需要使用到图片的地方用表达式: @drawable/icon
- 代码中使用:R.drawable.icon。Android环境本身就会根据索引找到对应的图片
3.6 layout布局资源(/res/layout目录)
一般在Android项目中定义了Layout资源:
- 在XML文件中可以通过如下语法格式来访问它:@layout/<file_name>
- 在Java代码中则按如下语法格式来访问它:R.layout.<file_name>
3.7 menu布局资源(/res/menu目录)
一般在Android项目中定义了menu资源:
- 在XML文件中可以通过如下语法格式来访问它:@menu/<file_name>
- 在Java代码中则按如下语法格式来访问它:R.menu.<file_name>
3.8 自适应不同屏幕资源
Android应用的特点:屏幕尺寸、分辨率差别非常大,但应用要在所有的设备上都能正常运行。为了适应不同屏幕的资源,最简单做法就是为不同屏幕尺寸、不同屏幕分辨率提供相应的布局文件、Drawable资源。
通常来说,屏幕资源需要考虑如下3个方面:
- 屏幕尺寸:small(小屏幕)、normal(中屏幕)、large(大屏幕)、xlarge(超大屏幕)
- 屏幕分辨率:ldpi(低分辨率)、mdpi(中分辨率)、hdpi(高分辨率)、xhdpi(超高分辨率)
- 屏幕方向:分为land(横屏)和port(竖屏)两种,需要在res目录下建立layout-port和layout-land两个目录,分别放置竖屏和横屏两种布局文件,以适应对横屏竖屏自动切换。
布局资源、Drawable资源目录的自动选取说明如下:
- Android 默认把drawable目录分为4个(drawable-xhdpi | drawable-hdpi | drawable- mdpi | drawable-ldpi),这四者主要是根据不同的分辨率会选择不同的drawable资源文件。
- 布局文件layout目录(layout-small | layout-normal | layout-large | layout-xlarge),四者主要是根据不同的分辨率会选择不同的layout布局文件。
3.9 关于资源引用的特殊说明
android系统对所有的xml资源文件其实是不加区别的,觉得values资源类型的不在于放在什么什么文件,而在于标签名,比如string-array的标签名决定了这是一个array资源。理解了原理,但最后还是建议将这些资源放在对应的位置上,这也算是Android不成文的规定。
4 使用Drawable资源(/res/drawable)
Drawable资源通常保存在/res/drawable目录,实际上可能保存在/res/drawable-ldpi,/res/drawable-mdpi,/res/drawable-hdpi 目录下。
4.1 图片资源
@1 一般在Android项目中定义了图片资源
- 在XML文件中可以通过如下语法格式来访问它:@drawable/<file_name>
- 在Java代码中则按如下语法格式来访问它:R.drawable.<file_name>
@2 在程序中为了获取实际的Drawable对象,Resources提供了Drawable getDrawable(int ResId)方法获取
注意:Android要求图片资源的文件名必须符合Java的标识符命名规则,否则SDK无法为该图片在R类中生成资源索引
4.2 statelistdrawable资源
4.2.1 StateListDrawable基础
一个StateListDrawable是在xml文件中定义,根据该对象不同的状态,用几张不同的图片来代表相同的图形。StateListDrawable用于组织多个Drawable对象,会随着目标组件状态的改变而自动切换。比如,一个按钮,有多种状态,获取焦点,失去焦点,点击等等。使用StateListDrawable可以根据不同的状态提供不同的图片背景。
注意:在XML文件中描述这些状态列表。在唯一的一个<selector>标签下,使用<item>标签来代表一个图形。每个<item>标签使用各种属性来描述它所代表的状态所需要的drawable资源。状态再次发生改变时,都会从上到下遍历这个状态列表,第一个和它匹配的将会被使用(而不是去选择最适合的匹配)。
语法格式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize=["true" | "false"]
android:dither=["true" | "false"]
android:variablePadding=["true" | "false"] >
<item
android:drawable="@[package:]drawable/drawable_resource"
android:state_pressed=["true" | "false"]
android:state_focused=["true" | "false"]
android:state_hovered=["true" | "false"]
android:state_selected=["true" | "false"]
android:state_checkable=["true" | "false"]
android:state_checked=["true" | "false"]
android:state_enabled=["true" | "false"]
android:state_activated=["true" | "false"]
android:state_window_focused=["true" | "false"] />
</selector>
4.2.2 属性详细解读
关于StateListDrawable中XML属性,查看官方文档:StateListDrawable XML属性详细解读
4.2.3 使用实例
@1 这里主要是Button使用selector的一个实例,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 默认时的背景图片 -->
<item android:drawable="@drawable/pic1" />
<!-- 没有焦点时的背景图片 -->
<item android:state_window_focused="false"
android:drawable="@drawable/pic1" />
<!-- 非触摸模式下获得焦点并单击时的背景图片 -->
<item android:state_focused="true" android:state_pressed="true"
android:drawable= "@drawable/pic2" />
<!-- 触摸模式下单击时的背景图片 -->
<item android:state_focused="false" android:state_pressed="true"
android:drawable="@drawable/pic3" />
<!--选中时的图片背景 -->
<item android:state_selected="true"
android:drawable="@drawable/pic4" />
<!--获得焦点时的图片背景 -->
<item android:state_focused="true"
android:drawable="@drawable/pic5" />
</selector>
@2 这是一个EditText使用selector的一个实例,如下所示:
<?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="#eee"/>
</selector>
4.3 Layerdrawable资源
4.3.1 LayerDrawable基础
LayerDrawable是管理一组drawable对象的drawable(本质是图层叠加)。在LayerDrawable的drawable资源按照列表的顺序绘制,列表的最后一个drawable绘制在最上层。可以用于图层的叠加显示,还可以用于SeekBar这类控件重新绘制主题与效果。它所包含的一组drawable资源用多个<item>元素表示,一个<item>元素代表一个drawable资源。
语法格式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/black_lotus"
android:left="20dp"
android:top="20dp">
</item>
<item android:drawable="@drawable/black_lotus"
android:left="40dp"
android:top="40dp">
</item>
<item android:drawable="@drawable/black_lotus"
android:left="60dp"
android:top="60dp">
</item>
</layer-list>
4.3.2 属性详细解读
关于LayerDrawable中XML属性,查看官方文档:LayerDrawable XML属性详细解读
说明:在默认的情况下,所有的drawable item都会缩放到合适的大小来适应视图。因此,在一个layer-list中定义不同的位置可能会增加视图的尺寸和被自动缩放。为了避免被缩放,可以再<item>节点里加上<bitmap>元素来指定一个drawable,并且定义一些不会被拉伸的gravity属性,例如center。下面在item里面定义一个drawable,图片就会自动缩放以适应视图的大小。
<item android:drawable="@drawable/image" />
为了避免缩放,可以使用<bitmap>的子元素来指定drawable资源
<item><bitmap android:src="@drawable/image" android:gravity="center" /></item>
4.3.3 使用实例
@1 这是SeekBar使用layer-list的一个实例,如下所示:
<?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="@color/black" />
<!-- 定义轨道上已完成部分的外观-->
<item android:id="@android:id/progress"
android:drawable="@color/cyan" />
</layer-list>
@2 这是图形叠加的使用实例,如下所示:
<?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>
4.4 shapedrawable资源
4.4.1 shapedrawable基础
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:centerColor="integer"
android:endColor="color"
android:gradientRadius="integer"
android:startColor="color"
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>
4.4.2 属性详细解读
关于ShapeDrawable中XML属性,查看官方文档:ShapeDrawable XML属性详细解读
4.4.3 使用实例
@1 line的使用实例(线)
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<stroke
android:width="10dp"
android:color="#FF0000FF"
android:dashWidth="1dp"
android:dashGap="1dp" />
</shape>
@2 rectangle的使用实例(圆角矩形)
<?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" />
<!-- 设置边框 -->
<stroke android:width="3dip" android:color="#ff0" />
</shape>
@3 oval的使用实例(椭圆)
<?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>
@4 ring的使用实例(环形)
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="12dp"
android:innerRadiusRatio="1"
android:thickness="0dp"
android:thicknessRatio="4"
android:useLevel="false"
>
<stroke android:width="1dp" android:color="#ff0000" />
<solid android:color="#ff0000" />
</shape>
4.5 clipdrawable资源
4.5.1 ClipDrawable基础
ClipDrawable 是对一个Drawable进行剪切操作,可以控制这个drawable的剪切区域,以及相相对于容器的对齐方式,android中的进度条就是使用一个ClipDrawable实现效果的,它根据level的属性值,决定剪切区域的大小。
注意:ClipDrawable是根据level的大小控制图片剪切操作的,官方文档的note中提到:level的大小从0到10000,level为0时完全不显示,为10000时完全显示。是用Drawable提供的setLevel(int level)方法来设置剪切区域。
语法格式如下所示:
<?xml version="1.0" encoding="utf-8"?>
<clip
xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/drawable_resource"
android:clipOrientation=["horizontal" | "vertical"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"] />
4.5.2 属性详细解读
关于ClipDrawable中XML属性,查看官方文档:ClipDrawable XML属性详细解读
4.5.3 使用实例
这里使用动态实例(代码+配置的方式)来实现一个特殊效果{使用ClipDrawable对象调用setLevel方法控制截取图片的部分,因此本例设置一个定时器,让程序不断调用ClipDrawable的setLevel方法即可实现图片徐徐展开的效果}
@1 代码如下所示:
public class ClipDrawableTest extends AppCompatActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main4);
ImageView imageView = (ImageView) findViewById(R.id.image);
final android.graphics.drawable.ClipDrawable drawable = (android.graphics.drawable.ClipDrawable) imageView.getDrawable();
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x1233) {
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;
handler.sendMessage(msg);
if (drawable.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 300);
}
}
注意:定义ClipDrawable的用法是把Drawable进行转换的。
@2 my_clip.xml实现
关键在于android:sec="@drawable/my_clip",调用了这个配置文件。这个配置文件的内容是:
<?xml version="1.0" encoding="UTF-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/test"
android:clipOrientation="horizontal"
android:gravity="center">
</clip>
这里的关键是对齐方式和展示方向,即gravity和clipOrientation来控制展示效果。
@3 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" >
<ImageView
android:id="@+id/image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="@drawable/my_clip"
/>
</LinearLayout>
这一个clipDrawable的配置文件完成。调用一个clip配置文件来展示效果。