android px dp 转换

dip 转 px
public static int dip2px(Context context, float dipValue){
                final float scale = context.getResources().getDisplayMetrics().density;
                return (int)(dipValue * scale + 0.5f);
        }
        
px 转 dip
    public static int px2dip(Context context, float pxValue){
                final float scale = context.getResources().getDisplayMetrics().density;
                return (int)(pxValue / scale + 0.5f);
        }

根据google的推荐,像素统一使用dip,字体统一使用sp  

举个例子区别px和dip:

px就是像素,如果用px,就会用实际像素画,比个如吧,用画一条长度为240px的横线,在480宽的模拟器上看就是一半的屏宽,而在320宽的模拟器上看就是2/3的屏宽了。

而dip,就是把屏幕的高分成480分,宽分成320分。比如你做一条160dip的横线,无论你在320还480的模拟器上,都是一半屏的长度。


问题
为什么相同分辨率的手机显示的控件的大小不一样呢,例如都是320*480的屏幕宽度是320dp的,有的手机就能填满窗口,有的就差一点点。

原因:px和dp的转换公式:px = dp * (dpi / 160),可是源码中,这里的dpi是归一化后的dpi,可能值只有120(low)、160(medium)、240(high)、 320(xhigh)四种,而我之前理解的是实际设备真实的dpi!
就拿G7为例,G7的真实dpi是252,根据我以前的理解,310dp换算成px应该是:310 * (252 / 160) = 488像素,而G7水平方向是480px,310dp在这上面绝对满屏都不止了,事实上Android系统并没有拿252作为dpi来计算,而是将G7视 作hdpi设备,然后使用240dpi来计算最终像素,所以在G7上320dp刚好是:320 * (240 / 160) = 480像素,刚好满屏了,310dp确实要差一点点。

问题
dp的本质还是物理尺寸,难道不是吗?
尽管Android系统对待dp这事上,将所有设备视为四种:120(low)、160(medium)、 240(high)、320(xhigh),在160dpi上,160dp就是1英寸,在240dpi上,160dp还是1英寸,120dpi和 320dpi也还是1英寸,虽然他们占用的像素数不一样,但是最终显示出来的效果都是占用了屏幕上1英寸的范围。这套体系其实是非常合理的,一个宽为 160dp的按钮,它在所有设备上占用的物理尺寸应该是一样大才合理,这样他们对人眼所形成的张角才一样大,观看或者阅读的感觉才一致(姑且不考虑按钮的 背景是否一样细致)。这应该是Android系统引入dp概念的原因

问题
现实生活中真的只有以上四种不同像素密度的设备吗?
不可能。虽然所有这些设备都可以粗略地划分为low、medium、high、 xhigh四种密度,可是对于划在同一范围内但具有不同像素密度的两个设备来说,同样的dp最终所占用的物理尺寸是不一样的。举个例子,G7(HTC Desire)的屏幕尺寸是3.7英寸,分辨率是480*800,像素密度是252dpi,G10(HTC Desire HD)的屏幕尺寸是4.3英寸,分辨率同为480*800,像素密度是217dpi。假设现在有一个按钮,它的宽度设为100dp,由于G7和G10同被 划分为hdpi,那么在这两个设备上,这个按钮的实际宽度是:100 * (240 / 160) = 150像素,可由于这两个设备的实际像素密度是不一样的,所以真实的显示效果是:这个按钮在两个设备上的实际物理尺寸是不一样大的。而这,和 Android进入dp的概念是相悖的。


参考: http://www.cnblogs.com/fbsk/archive/2011/10/17/2215539.html
http://zhangkun716717-126-com.iteye.com/blog/1772696

你可能感兴趣的:(android px dp 转换)