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);