源代码目录: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所示。