- Android开发权威指南(第二版)
- 李宁编著
- 1528字
- 2024-12-21 14:46:13
10.4 值(values)资源
所有放到res/values目录中的资源都属于值资源(可以存放在任意的XML文件中)。但由于很多值资源都自成一体,所以这些资源将放到单独的章节进行介绍,例如,上一节介绍的字符串资源,还有后面的风格(Style)资源都会用大量的篇幅介绍。然而还有一些非常简单的值资源,例如,整数资源、布尔资源、数组资源、ID资源等,本节将会着重介绍这些值资源。
10.4.1 整数(Integer)资源
整数资源使用<integer>标签设置,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="height">75</integer>
<integer name="width">5</integer>
</resources>
在资源文件中使用下面的代码引用整数资源。
<TextView
android:layout_width="@integer/width"
android:layout_height="@integer/height"/>
下面是引用整数资源的Java代码。
int width = getResources().getInteger(R.integer.width);
int height = getResources().getInteger(R.integer.height);
10.4.2 尺寸(Dimension)资源
源代码目录:src/ch10/Dimension
尺寸资源是由一系列的浮点数组成的资源,这些资源需要在res/values目录的资源文件中定义,<dimen>标签用来定义尺寸资源。下面的代码定义了3个尺寸资源。
源代码文件:src/ch10/Dimension/res/values/dimension.xml
<resources>
<dimen name="size_px">50px</dimen>
<dimen name="size_in">1.5in</dimen>
<dimen name="size_sp">30sp</dimen>
</resources>
从上面的代码可以看出,在尺寸值后面是尺寸单位。Android支持如下6种尺寸单位。
px:表示屏幕实际的像素。例如,320*480的屏幕在横向有320个像素,在纵向有480个像素。
in:表示英寸,是屏幕的物理尺寸,每英寸等于2.54厘米。例如形容手机屏幕大小,经常说3.2(英)寸、3.5(英)寸、4(英)寸就是指这个单位。这些尺寸是屏幕的对角线长度。如果手机的屏幕是3.2英寸,表示手机的屏幕(可视区域)对角线长度是3.2*2.54 = 8.128厘米。读者可以去量一量自己的手机屏幕,看和实际的尺寸是否一致。
mm:表示毫米,是屏幕的物理尺寸。
pt:表示一个点,是屏幕的物理尺寸,大小为1英寸的1/72。
dp:与密度无关的像素,这是一个基于屏幕物理密度的抽象单位。密度可以理解为每英寸包含的像素点个数(单位是dpi),1dp实际上相当于密度为160dpi的屏幕的一个点。也就是说,如果屏幕的物理密度是160dpi时,dp和px是等效的。现在用实际的手机屏幕说明一下。一块拥有320*480分辨率手机屏幕,如果宽度是2英寸、高度是3英寸,这块屏幕的密度就是160dpi。如果屏幕大小未变,而分辨率发生了变化,例如,分辨率由320*480变成了480*800,这时屏幕的物理密度就变大了(大于160dpi)。这就意味着屏幕每英寸可以显示更多的像素点,屏幕的显示效果就更细腻了。假设一个按钮的宽度使用dp作为单位,在160dpi时设为160dp,而在更高的dpi下(如320dpi),按钮宽度看上去和160dpi时的屏幕一样。这是由于系统在发现屏幕的密度不是160dpi时,会计算一个转换比例,然后用这个比例与实际设置的尺寸相乘就得出新的尺寸。计算比例的方法是目标屏幕的密度除以160。如果目标屏幕的密度是320dpi,那么这个比例就是2。如果按钮的宽度是160dp,那么在320dpi的屏幕上的宽度就是320个像素点(dp是抽象单位,在实际的屏幕上应转换成像素点)。从这一点可以看出,dp可以自适应屏幕的分辨率。不管屏幕分辨率如何变化,屏幕上控件的相对位置和尺寸总会保持不变。如果将按钮的宽度设成160px,那么在320dpi的屏幕上仍然会是160个像素点,看上去按钮宽度只是160dpi屏幕的一半。Android官方建议设置表示宽度、高度、位置等属性时应尽量使用dp作为尺寸单位。除了使用dp,也可以使用dip,它们是等效的。要注意的是,dpi表示密度,而dip=dp。在使用时不要弄混了。
sp:与比例无关的像素。这个单位与dp类似。不过除了自适应屏幕密度外,还会自适应用户设置的字体。因此,Android官方推荐在设置字体大小时(如android:textSize属性)应尽量使用sp作为尺寸单位。
下面的代码引用了dimension.xml文件中定义的尺寸资源。
源代码文件:src/ch10/Dimension/res/layout/main.xml
<TextView android:layout_width="200px" android:layout_height="wrap_content"
android:background="#FFF" android:textColor="#000" android:text="宽度:200像素" />
<TextView android:layout_width="@dimen/size_in" android:layout_height="wrap_content"
android:background="#FFF" android:text="宽度:1.5英寸"
android:layout_marginTop="10dp" android:textColor="#000"/>
<TextView android:layout_width="20mm" android:layout_height="wrap_content"
android:background="#FFF" android:text="宽度:20毫米"
android:layout_marginTop="10dp" android:textColor="#000"/>
<TextView android:layout_width="100pt" android:layout_height="wrap_content"
android:background="#FFF" android:text="宽度:100 points"
android:layout_marginTop="10dp" android:textColor="#000"/>
<TextView android:layout_width="200dp" android:layout_height="@dimen/size_px"
android:background="#FFF" android:text="宽度:200 dp\n高度:50 px"
android:layout_marginTop="10dp" android:textColor="#000"/>
<TextView android:layout_width="200dp" android:layout_height="wrap_content"
android:background="#FFF" android:textSize="@dimen/size_sp" android:text="字体尺寸:30sp"
android:layout_marginTop="10dp" android:textColor="#000"/>
可以使用如下3个方法获取尺寸资源,这些方法会根据相应的尺寸单位返回与其对应的像素值。这3个方法的区别是返回值的类型不同(第1个方法返回float类型的值,后两个方法返回int类型的值)。
floatsize1 = getResources().getDimension(R.dimen.size_in)));
// 对size1采用舍去的方式返回对应的整数,例如,size1=25.6,size2的值是25
int size2 = getResources().getDimensionPixelOffset(R.dimen.size_in)));
// 对size1采用四舍五入的方式返回对应的整数,例如,size1=25.6,size3的值是26
int size3 = getResources().getDimensionPixelSize(R.dimen.size_in)));
如果想直接获取尺寸大小(不转换成像素),可以使用下面的代码。
TypedValue outValue = new TypedValue();
// getValue方法的第3个参数如果为true,表示即使资源值引用了另外的资源,系统
// 会通过递归的方法获取最终的资源值
getResources().getValue(R.dimen.size_in, outValue, true);
// 由于getValue方法并没有直接返回尺寸资源的值,所以需要使用complexToFloat方法进行转换
// value的值是1.5
float value = TypedValue.complexToFloat(outValue.data);
现在运行本例,会看到用各种尺寸资源设置不同属性的显示效果,如图10-12所示。
▲图10-12 尺寸资源
10.4.3 布尔(Boolean)资源
布尔资源使用<bool>标签设置,标签值只能是true或false,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="screen_small">true</bool>
<bool name="adjust_view_bounds">true</bool></resources>
在资源文件中使用如下方式引用布尔资源。
<ImageView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:src="@drawable/logo"
android:adjustViewBounds="@bool/adjust_view_bounds" />
下面是引用布尔资源的Java代码。
boolean screenIsSmall = getResources().getBoolean(R.bool.screen_small);
10.4.4 颜色(Color)资源
颜色资源用于指定颜色值,使用<color>标签设置,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="opaque_red">#f00</color>
<color name="translucent_red">#80ff0000</color>
</resources>
在资源文件中使用颜色资源的代码如下:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textColor="@color/translucent_red"
android:text="Hello"/>
下面是引用颜色资源的Java代码。
int color = getResources().getColor(R.color.opaque_red);
Android允许将颜色值作为资源保存在资源文件中。保存在资源文件中的颜色值用井号(#)开头,Android支持如下4种颜色值表示方式。
#RGB。
#ARGB。
#RRGGBB。
#AARRGGBB。
其中R、G、B表示三原色,也就是红、绿、蓝,A表示透明度,也就是Alpha值。A、R、G、B的取值范围都是0~255。R、G、B的取值越大,颜色越深。如果R、G、B都等于0,表示的颜色是黑色,都为255,表示的颜色是白色。R、G、B三个值相等时表示灰度值。R、G、B总共可表示16777216(2的24次方)种颜色。A取0时表示完全透明,取255时表示不透明。如果采用前两种颜色值表示法,A、R、G、B的取值范围是0~15,这并不意味着是颜色范围的256个值的前15个,而是将每一个值扩展成两位。例如,#F00相当于#FF0000;#A567相当于#AA556677。从这一点可以看出,#RGB和#ARGB可设置的颜色值并不多,它们的限制条件是颜色值和透明度的8位字节的高4位和低4位相同。其他的颜色值必须使用后两种形式设置。
10.4.5 ID资源
ID资源实际上就是android:id属性的值,使用<item>标签设置,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="button_ok" />
<item type="id" name="dialog_exit" />
</resources>
资源文件中引用ID资源的代码如下:
<Button android:id="@id/button_ok"……/>
通常在设置android:id属性时都会在“@”和“id”之间加一个“+”,代码如下:
<Button android:id="@+id/button_ok"……/>
这个“+”的含义是如果ID资源不存在,系统会自动创建一个ID资源,如果ID资源存在,系统会忽略“+”。通过这种策略避免在设置android:id属性值时都要定义ID资源的繁琐方式。
注意
尽管所有可接收ID资源的属性都可以使用“+”,但建议只在android:id属性值中使用“+”。这是因为其他的属性都需要使用已经存在的ID资源对应的控件,如果使用了“+”,当指定的ID资源不存在时系统会自动创建一个ID资源,这样尽管ID资源存在了,但并未对应任何的控件,可能会使程序抛出异常,也不会使程序达到预先设定的效果。例如,<RelativeLayout>标签的android:layout_marginLeft属性就必须设置一个已经与某个控件绑定的ID资源。
10.4.6 整数数组(Integer-Array)资源
整数数组资源用于存储一组整数,用<integer-array>标签设置,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="bits">
<item>4</item>
<item>8</item>
<item>16</item>
<item>32</item>
</integer-array>
</resources>
引用整数数组资源的Java代码如下:
int[] bits = getResources().getIntArray(R.array.bits);
10.4.7 类型数组(Typed-Array)资源
类型数组资源可以将其中资源作为数组存储,因此也可以称为资源数组资源。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="icons">
<item>@drawable/home</item>
<item>@drawable/settings</item>
<item>@drawable/logout</item>
</array>
<array name="colors">
<item>#FFFF0000</item>
<item>#FF00FF00</item>
<item>#FF0000FF</item>
</array>
</resources>
引用类型数组资源的Java代码如下:
Resources res = getResources();
TypedArray icons = res.obtainTypedArray(R.array.icons);
Drawable drawable = icons.getDrawable(0);
TypedArray colors = res.obtainTypedArray(R.array.colors);
int color = colors.getColor(0,0);