转载自:http://www.cnblogs.com/xilinch/p/4444833.html
最近在看了许多关于dp-px,px-dp,sp-px,px-sp之间转化的博文,过去我比较常用的方式是:public static int convertDipOrPx (Context context, int dip) { float scale = context.getResources().getDisplayMetrics().density; return (int )(dip*scale + 0.5f *(dip>=0 ?1 :-1 )); } public static int convertPxOrDip (Context context, int px) { float scale = context.getResources().getDisplayMetrics().density; return (int )(px/scale + 0.5f *(px>=0 ?1 :-1 )); }
然后看到了一种新的转化方式,代码如下public static int dp2sp(float dpVal) { return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, MyAppliction.getInstance() .getApplicationContext() .getResources() .getDisplayMetrics() ) ) ; } public static int sp2dp(float spVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, MyAppliction.getInstance() .getApplicationContext() .getResources() .getDisplayMetrics() ) ); }
码农对TypedValue充满好奇,通过查询官网了解该类
TypedValue —android.util.TypedValue Container for a dynamically typed data value. Primarily used with Resources for holding resource values.
翻译过来就是:这个类是工具类,作为一个动态容器,它存放一些数据值,这些值主要是resource中的值。
我们来理解一下:resource中到底有哪些值?layout、drawable、string、style、anim、dimens、menu、colors、ids这些值一些和屏幕适配有直接的关系。
有一些方法必然是可以读取这些资源文件信息的,比如:getDimension (DisplayMetrics metrics)
再看具体的方法:
applyDimension(int unit, float value,DisplayMetrics metrics) 第一个参数是单位,第二个参数是对应值,第三个你懂的,封装了显示区域的各种属性值。
对于applyDimension(int unit, float value,DisplayMetrics metrics)中的代码我们来看下1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static float applyDimension (int unit, float value , DisplayMetrics metrics ) { switch (unit) { case COMPLEX_UNIT_PX: return value ; case COMPLEX_UNIT_DIP: return value * metrics.density; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0 f/72 ); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0 f/25.4 f); } return 0 ; }
其中单位为dip的,将其转化为密度*值,也就是像素值,而单位sp的也将其转化为px值,因此该方法可以能进行 dip–>px sp– >px 因此上面 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics ); 这个方法肯定不能将sp转化为dp,我们判断 dp2sp(50) = 150 sp2dp(50) = 150 convertDipOrPx(50) = 150 convertPxOrDip(50) = 17 将代码运行实际结果与判断结果一致。
接下来我们继续分析 TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value ,DisplayMetrics ); 该方法系统本意是用来做什么的? 查看官方说明: Converts an unpacked complex data value holding a dimension to its final floating point value.
这里就把对应的值转化为实际屏幕上的点值,也就是像素值。 如果是TypedValue.COMPLEX_UNIT_DIP,则乘以显示密度density。 而如果是TypedValue.COMPLEX_UNIT_SP,则乘以像素密度scaledDensity。
我们继续刨根追底 density和scaledDensity的区别在于 density:The logical density of the display.显示密度density = dpi/160 scaledDensity:A scaling factor for fonts displayed on the display.显示字体的缩放因子 = density
实际上两者的值一样,为了验证这个结论我们随便找两台机器小米2S和华为p7,取出density和scaledDensity是一致的,P7为3.0,小米2S = 2.0
因此本文结论转化dp-px,px-dp,sp-px,px-sp
使用下面方法:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public static int convertDipOrPx (Context context, int dip) { float scale = context.getResources().getDisplayMetrics().density; return (int )(dip*scale + 0.5f *(dip>=0 ?1 :-1 )); } public static int convertPxOrDip (Context context, int px) { float scale = context.getResources().getDisplayMetrics().density; return (int )(px/scale + 0.5f *(px>=0 ?1 :-1 )); } public static int sp2px (Context context, float spValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int ) (spValue * fontScale + 0.5f ); } public static int px2sp (Context context, float pxValue) { float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int ) (pxValue / fontScale + 0.5f ); }