在碎片化的Android设备中,设备的屏幕大小和密度也有很多类型,所以android帮我们定义了
四种大小类型:small,normal,large,xlarge
四种屏幕密度:ldpi(120dpi),mdpi(160dpi),hdpi(240dpi),xhdpi(320dpi)
(屏幕密度可以理解成单位面积的区域上有多少像素点,像素点越多,屏幕密度越大,显示得越清晰)
我们一般会用dp来定义长度,用sp来定义文字大小。
为什么要用dp来定义长度呢?原因很简单,当不使用dp定义长度的时候,ui元素会在低密度的屏幕上显示得很大或者在高密度的屏幕上显示的很小,如下图
但使用dp定义长度后效果就好多了,如下图
在实际工作中,ui的小伙伴们是以px来标识出长度的,这样我们就需要将px转换成dp,使用以下公式转换:
px = dp * (dpi / 160);
(ldpi(120dpi),mdpi(160dpi),hdpi(240dpi),xhdpi(320dpi))
我在网上看见类似以下的代码:
-
// The gesture threshold expressed in dp private static final float GESTURE_THRESHOLD_DP = 16.0f; // Get the screen‘s density scale final float scale = getResources().getDisplayMetrics().density; // Convert the dps to pixels, based on density scale mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f); // Use mGestureThreshold as a distance in pixels...
使用以上的代码来把dp转换成px是因为针对特定的场景的,例如当用户的手指移动了16px以上就认为是一个scroll或者fill的手势,但是这样就出现一个问题,屏幕密度越高,移动的距离就会越短,这样在xhdpi的屏幕上,这个scroll或者fill的动作对于用户来说是太敏感了!
当我们使用图片的时候也要注意类似的问题
这里我首先介绍两个定义
1.pre-scaling of resources:这个很简单,我们的项目中有drawable-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi这几个文件夹中就放着pre-scaling的图片
2.auto-scaling of pixel dimensions and coordinates:当在manifest文件中设置android:anyDensity=“false”,或者用编码的方式设置bitmap的inScaled为false的时候,系统会自动在显示的时候转换绝对的px坐标和长度,使ui元素还是能正确地以在mdpi中应该显示的大小显示出来。
接下来介绍一个bitmap对象在runtime期间是如何转换的。
当我们创建一个 bitmap 对象的时候,系统首先会假设该bitmap对象是在mdpi上设计的,默认地,系统会在显示的时候auto-scaling bitmap。如果bitmap没有设置density属性,系统就会使用auto-scaling去处理它,auto-scaling处理的结果就像你没有为该资源在不同的dpi上设置相应的资源造成的效果一样。
如果你设置pre-scaling设置为false,那么系统就会在显示的时候使用auto-scaling,换句话,这样做就是用auto-scaling去代替了pre-scaling,这样会浪费更多的cpu资源但是占用了更少的存储空间。
另外我们还可以使用ViewConfiguration去获取系统的公共长度,速度和时间,例如
<span class="kwd" style="color:#0088;">private</span><span class="pln" style="color:#000000;"> </span><span class="kwd" style="color:#0088;">static</span><span class="pln" style="color:#000000;"> </span><span class="kwd" style="color:#0088;">final</span><span class="pln" style="color:#000000;"> </span><span class="kwd" style="color:#0088;">int</span><span class="pln" style="color:#000000;"> GESTURE_THRESHOLD_DP </span><span class="pun" style="color:#66660;">=</span><span class="pln" style="color:#000000;"> </span><span class="typ" style="color:#66066;">ViewConfiguration</span><span class="pun" style="color:#66660;">.</span><span class="kwd" style="color:#0088;">get</span><span class="pun" style="color:#66660;">(</span><span class="pln" style="color:#000000;">myContext</span><span class="pun" style="color:#66660;">).</span><span class="pln" style="color:#000000;">getScaledTouchSlop</span><span class="pun" style="color:#66660;">();</span>
ViewConfiguration中以getScaled开头的方法保证了返回的px值都是适应当前的屏幕的。
Android中dp、sp、px的转换和区别。
apk的资源包中
当屏幕density=240时,使用hdpi 标签的资源 当屏幕density=160时,使用mdpi标签的资源 当屏幕density=120时,使用ldpi标签的资源。 不加任何标签的资源是各种分辨率情况下共用的。 布局时尽量使用单位dip,少使用px
dp与px换算公式:
pixs =dips * (densityDpi/160).
dips=(pixs*160)/densityDpi
/** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); }
dp与px转换的方法:
public static int dip2px(Context context, float dipValue){ final float scale = context.getResources().getDisplayMetrics().density; return (int)(dipValue * scale +0.5f); }public static int px2dip(Context context, float pxValue){ final float scale = context.getResource().getDisplayMetrics().density; return (int)(pxValue / scale +0.5f); }
名词 |
解释 |
Px (Pixel像素) |
不同设备显示效果相同。这里的“相同”是指像素数不会变,比如指定UI长度是100px,那不管分辨率是多少UI长度都是100px。也正是因为如此才造成了UI在小分辨率设备上被放大而失真,在大分辨率上被缩小。 |
Screen Size (屏幕尺寸) |
一般所说的手机屏幕大小如1.6英寸、1.9英寸、2.2英寸,都是指的对角线的长度,而不是手机面积。我们可以根据勾股定理获取手机的宽和长,当然还有面积。 |
Resolution (分辨率) |
指手机屏幕垂直和水平方向上的像素个数。比如分辨率是480*320,则指设备垂直方向有480个像素点,水平方向有320个像素点。 |
Dpi (dots per inch 像素密度) |
指每英寸中的像素数。如160dpi指手机水平或垂直方向上每英寸距离有160个像素点。假定设备分辨率为320*240,屏幕长2英寸宽1.5英寸,dpi=320/2=240/1.5=160 注意:该值对应于DisplayMetrics类中属性densityDpi的值 |
Density (密度) |
指每平方英寸中的像素数。 Density=Resolution/Screen size 注意:在DisplayMetrics类中属性density的值为dpi/160,可用于px与dip的互相转换 |
Dip (Device-independent pixel,设备独立像素) |
同dp,可作长度单位,不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。dip和具体像素值的对应公式是dip值 =设备密度/160* pixel值,可以看出在dpi(像素密度)为160dpi的设备上1px=1dip |
Sp (ScaledPixels 放大像素) |
主要用于字体显示(best for textsize)。根据 google 的建议,TextView 的字号最好使用 sp 做单位,而且查看TextView的源码可知 Android 默认使用 sp 作为字号单位。 |