老子曾说“天下难事必作于易,天下大事必作于细”,其实Android开发也是如此。博主一开始学android的时候,对像素单位不知其所以然,只知一根筋的填数字,结果在模拟器上跑好好的界面,拿到真机上就显示得东倒西歪,害得自己使劲的找bug,这都是没打好基础的缘故呀。所以一开始就把像素这种基础概念弄清楚,后面会少走很多弯路,开发起来也会更加得心应手。 android支持如下像素单位:px(像素)、in(英寸)、mm(毫米)、pt(磅,1/72英寸)、dp(与设备无关的显示单位)、dip(就是dp)、sp(用于设置字体大小),其中常用的就是px、dp和sp三种。 个人理解,px是android屏幕上可显示的最小单位,这个与物理设备的显示屏有关系,一般来说,同样尺寸的屏幕(比如说都是4.7寸的手机),看起来越清晰的屏幕,其像素密度越高,以px计量的分辨率就越大。 而dp与物理设备无关,只与屏幕的尺寸有关,一般来说,同样尺寸的屏幕,以dp计量的分辨率都是一样的,不管这个手机是哪个厂家生产,dp大小都一样。 至于sp,其原理跟dp差不多,那为什么说sp专门用于设置字体大小呢?android手机在系统设置里面可以设置字体的大小(小、普通、大、超大),设置普通字体时,同数值dp和sp的文字看起来是一样大的,但如果设置为大字体,用dp设置大小的文字没有变化,而用sp设置大小的文字就变大了。所以说,dp与系统设置的字体大小没有关系,而sp会随系统设置的字体大小来变大或者变小。
dp和px之间的联系,取决于具体设备上的像素密度,像素密度就是DisplayMetrics里的density参数。当density=1.0时,表示一个dp值对应一个px值;当density=1.5时,表示两个dp值对应三个px值;当density=2.0时,表示一个dp值对应两个px值。具体的转换函数如下所示:
/**
* 根据手机的分辨率从 dp 的单位 转成为 px(像素) 。
*/
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
/**
* 根据手机的分辨率从 px(像素) 的单位 转成为 dp 。
*/
public static int px2dip(Context context, float pxValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
代码里面的加0.5f,其目的是四舍五入,因为浮点数强制转为整型时,小数点后面数值会被直接咔嚓掉,所以如果原小数位后大于0.5,再加0.5就会进一,就曲线实现了四舍五入。
xml布局文件中,因为设备无关性,所以除了sp用于设置文字大小外,其余要用大小的地方都是写dp。但在代码之中,情况又不同,android用于设置大小的函数都是以px为单位。不管是LayoutParams里的width和height,还是setMargins和setPadding,其参数单位都是px,所以要想在代码中使用dp设置布局大小或者间距,得先把dp值转换成px值才好。代码示例
int dip_10 = Utils.dip2px(mContext, 10L);
LinearLayout.LayoutParams titleParams = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
titleParams.setMargins(dip_10, dip_10, dip_10, dip_10);