Pro Android学习笔记(三):了解Android资源(上)
在Android开发中,资源包括文件或者值,它们和执行应用捆绑,无需在源代码中写死,因此我们可以改变或替换他们,而无需对应用重新编译。
了解资源构成
参考阅读Android学习笔记(三八):资源resource(上)、XML解析(XmlPullParser),Android学习笔记(三九):资源resource(下)。
Strings资源。位于res/values下,可以有一个或多个xml文件。其中最为常见的是strings.xml,对于demo这类小例子,为了方便常全部都放在strings.xml中,但实际开发中,应进行合理组织。下面事xml文件的例子:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Pro Android</string> <string name="action_settings">Settings</string> <string name="resource_test">Understanding Resources</string> </resources> |
需要留意,对于标准的xml文件,有xmlns来指明schema,在此可以省略。如果非要加上,可以为:<resources xmlns="http://schemas.android.com/apk/res/android" >
。每定义一个string,在R.java文件中将自动生成ID,由此可以通过ID,如R.string.app_name进行对应,ID事int,但Android或根据需要转换为对应的string。
public final class R { … … public static final class string { public static final int action_settings=0x7f050001; public static final int app_name=0x7f050000; public static final int resource_test=0x7f050002; } … … } |
Layout资源。res/layout下放着关键的View,每个activity或者每个screen要单独xml来描述。在代码用setContentView ( R.layout.xxxx ) 来进行映射。而layout xml文件中的view,则用R.id.xxxx来映射,可以通过findViewById来获取具体view的对象。
Resource Reference Syntax资源参考语法。用于分配在Android xml文件某个资源的ID的语法称为资源参考语法,具体为@[ package:] type/name,例如android:id="@+id/t1"。”+”表示如果t1的id没有定义为资源,去为它定义一个唯一的Id号码。实际上,我们可以预先定义id,以后再使用,方式如下,在res/values下的xml文件中进行定义。定义后,我们将在R.java文件中发现有关的R.id.t2的定义,如是,我们将使用android:id="@id/t2"。
<resources> <item type="id" name="t2"/> </resources> |
这里的type是对应R.java里面的资源类别的namespace,例如R.string则对应为string。此外可以是drawable,id,layout,string,attr,plurals,string-array(在R.java中为R.array)。这里的name,是指资源的名称,也对应R.java中ID名字。如果没有package,就是使用本地资源,和本app的R.java中。Andriod同时也提供了一些组件,例如ListView,使用<ListView android:id=”@android:id/list”…… />,这使用了android.R.java文件,实时上,我们可以使用其他包名,用该包下的R.java文件来解释。
编译和非编译的资源。资源来源两类文件:XML和raw文件,对应的也可以分为编译为二进制格式的,和非编译直接copy的。对于一般的资源XML文件,需要将XML的节点翻译的ID,所以需要编译为binary。其中res/xml中可放置任何XML格式的文件,如们自定的,可以通过R.xml.<file_name>来指向该资源,并用Android提供的XML reader来解析,如XMLPullPaser。
非编译为binary的文件位于res/raw,和所有res/下的资源一样,可用R.raw.<file_name>来获取该资源。读取是需使用stream-based的API,如下。audio和video文件属于这类raw文件,当然如果我们需要,也可以将一个xml文件放入res/raw目录下,作为raw文件来使用。
BufferedReader reader=new BufferedReader(new InputStreamReader(getResources().openRawResource(R.raw.w_city_code))); |
主要的关键资源
String Arrays。位于res/values/*.xml,格式如下:
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="rt_test_array"> <item>one</item> <item>two</item> <item>three</item> </string-array> </resources> |
在R.java中自动生成ID,可以在用R.array.xxxx来调用
public final class R {
public static final class array {
public static final int rt_test_array=0x7f050000;
}
… …
}
在程序中可以如下调用
//通过getResources()获取activity的resource对象,通过该对象获取string-array资源
String strs[] = getResources().getStringArray(R.array.rt_test_array);
for(String s: strs){
……
}
复数Plurals。这对中文而言没有什么意义,但是在英文中,有There is one egg. 和There are 5 eggs. 的区别。需要在信息表达方面进行区分对待,plurals就是针对此进行处理。
在quantity中有效的选择显示有6个,但是如果locale为en时,实际有效的是“one”和“other”,设置其余的,经试验,并无效果。书中言,对于其他的语言设置也是这样,除了捷克语,对于2-4,对应为few。
Resources res = getResources(); //获取资源对象
//res.getQuantityString(),第一个参数为plurals的ID,第二参数为0,对应quantity的选择,由于有效的只有1和其他,则对应other,因此s1为There are %d eggs.
String s1= res.getQuantityString(R.plurals.rt_test_plurals, 0);
//第二个参数为0,对应other,第三个参数为2,是根据format对%d的填充,即为There are 0 eggs.
s1= res.getQuantityString(R.plurals.rt_test_plurals, 0,2);
//第二个参数为1,对应one,即为There is 1 egg.
s1= res.getQuantityString(R.plurals.rt_test_plurals, 1);
//第二个参数为1,对应one,由于format没有需要填入,为There is 1 egg.
s1= res.getQuantityString(R.plurals.rt_test_plurals, 1,1);
//第二个参数为2,对应other,由于format有input,为There are 6 eggs.
s1= res.getQuantityString(R.plurals.rt_test_plurals, 2,6);
Wei:经过试验,在XML中用%s来替代%d是可行的,但是如果input的数目超过1个,如2个或以上,则在编译时会报错。plurals就只是为了处理西文中复数的问题,不要搞得太复杂。对于上面的例子,第二和第三参数应该匹配,这样才便于阅读,例如res.getQuantityString(R.plurals.rt_test_plurals,6,6)。
再谈String。string资源可以带有输入,可以带有html格式。我们看看以下的string资源的获取和输出。
我们通过下面的代码在TextView tv中进行输入。
tv.append ( getString(R.string.rt_simple_string)) ); //特别留意最后两个。在资源中带有HTML的格式,如果仍用<b></b>,在获取资源时,这部分信息会消失,需要用< 和 > 来表示左右尖括号。多少有些麻烦。此外要使HTML格式有效,需要告知TextView这是一个HTML格式,否则会直接将<b></b>作为字符串内容显示。下面试验再次证明需要将尖括号改写。 tv.append ( Html.fromHtml( getString(rt_html_string1) + "<br/>") ); |
我们可以在view中直接引用string,如 andriod:text=”@string/rt_simple_string”。
Color。color资源同样在res/values/下面定义。
<color name="rt_blue">#0000f0</color>
代码调用如下。处理我们定义,我们还可以使用Android预定义的一些颜色,具体可以参考http://developer.android.com/reference/android/R.color.html#background_light。
int color = getResources().getColor(R.color.rt_blue);
tv.setTextColor(color);
tv.setBackgroundColor(getResources().getColor(android.R.color.background_dark));
Dimension。同样,在res/values/下任何xml文件可以定义
<dimen name="rt_dp">5dp</dimen>,
其中dp为Android的尺寸单位,Android长度单位详解(dp、sp、px、in、pt、mm、dip) ,android中定义的dimension单位有以下这些:
px(Pixels ,像素) :对应屏幕上的实际像素点。
in(Inches ,英寸) :屏幕物理长度单位。
mm(Millimeters ,毫米):屏幕物理长度单位。
pt(Points ,磅) :屏幕物理长度单位,1/72英寸。
dp(与密度无关的像素) :逻辑长度单位,在 160 dpi 屏幕上,1dp=1px=1/160英寸。随着密度变化,对应的像素数量也变化,但并没有直接的变化比例。
dip :与dp相同,多用于Google示例中。
sp(与密度和字体缩放度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。
从资源中获取dimension如下,可以在setTextSize( )等场合使用dimension,或者直接在XML中设置android:textSize="@dimen/rt_dp"
float dimen = getResources().getDimension(R.dimen.rt_dp);
Image资源。由于手机尺寸的不同,同一个图片,可制造成不同的尺寸,放置在res/drawable-?dpi中,系统会进行自动选择,ic_launcher图标。我们也可以不考虑手机实际尺寸,使用同一个图标,可以放置在res/drawable中。试验,为了简单,采用同一尺寸。图片的格式可以是*.gif,*.jpg和*.png。
实验中我们将sample_image.png放置到drawble。在XML中可以如下引用
第一个图中图片出现伸拉 |
<Button android:id="@+id/vt_button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/resource_test" android:background="@drawable/sample_image"/> <ImageButton android:id="@+id/vt_img_button3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:contentDescription="@string/resource_test" android:src="@drawable/sample_image"/> |
当然,也可以在java编码中来调用。如下
Drawable d = getResources().getDrawable(R.drawable.sample_image);
button.setBackground(d);
等同于下面
button.setBackgroundResource(R.drawable.ic_launcher);
绝大部分的view都具有setBackground的方法。
Wei:在Android的API Guides中这样写道:A bitmap graphic file (<.png, .jpg, or .gif). Creates a BitmapDrawable. 但getDrawable()返回的Drawble。同样根据API Guides,我们可以通过设置bitmap xml来,而这个输出BitmapDrawable,该XML放置在res/drawable/下,如下
<?xml version="1.0" encoding="utf-8"?>
<bitmap
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@[package:]drawable/drawable_resource"
android:antialias=["true" | "false"]
android:dither=["true" | "false"]
android:filter=["true" | "false"]
android:gravity=["top" | "bottom" | "left" | "right" | "center_vertical" |
"fill_vertical" | "center_horizontal" | "fill_horizontal" |
"center" | "fill" | "clip_vertical" | "clip_horizontal"]
android:tileMode=["disabled" | "clamp" | "repeat" | "mirror"] />
Color-Drawable资源。在了image外,drawable资源还可以是color-drawable,也就是一个颜色方框。定义颜色方框,可以在res/values中任何XML文件中加入:
<resource>
<drawable name="red_rectangle">#f00</drawable>
<drawable name="blue_rectangle">#0000ff</drawable>
<drawable name="green_rectangle">#00f0f0</drawable>
</resource>
在view的xml中,同样可以设置
android:background="@drawable/red_rectangle"
或者在java code里面
Button b1 = (Button)findViewById(R.id.vt_button0);
ColorDrawable grDrawble = (ColorDrawable)getResources().getDrawable(R.drawable.green_rectangle);
b1.setBackground(grDrawble);
在实际效果如下
一片颜色不好看,要进行复杂地设置,需要单独在一个 xml文件中,通过shape来描述。该文件放置在res/drawable/目录下。下面是my_round_red_retangle.xml的内容
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="#f0600000"/> <!-- 这是底层 -->
<stroke android:width="3dp" android:color="#ffff8080" /> <!-- 这是边框 -->
<corners android:radius="13dp"/> <!-- 设置圆角 -->
<padding android:left="10dp" android:top="10dp" android:bottom="10dp" android:right="10dp" />
</shape>
在java code的使用如下,也可以用android:background="@drawable/my_round_red_rectangle"。Wei:根据Android API Guide,使用的类型是SpanDrawable,如是,会出错,还是用用GradientDrawable。
Button b2 = (Button)findViewById(R.id.vt_button2);
GradientDrawable roundTangle = (GradientDrawable) getResources().getDrawable(R.drawable.my_round_red_rectangle);
b2.setBackground(roundTangle);
再给出一个例子
<?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"/>
<corners android:radius="8dp"/>
</shape>
相关链接: 我的Android开发相关文章