[关闭]
@coder-pig 2017-09-22T06:24:00.000000Z 字数 3920 阅读 812

2.13.1 单位与相关名词

Tutorial


官方API Guides的最佳实践中对此已经有详细的描述了,可以直接看官方的:
https://developer.android.com/guide/practices/screens_support.html


1.相对单位与绝对单位

对于计量单位,习惯性分为:「相对单位」与「绝对单位」,前者 根据
不同的情景表现出不同的大小,比如Android里的dp,px,sp等,而后者则是
指定了一个标准,比如mm(毫米),写死了,1mm也就那么多,无论什么情况下
都是那么多,而常用的绝对单位还有in(英寸,2.54cm),pt(磅,印刷行业
常用单位),另外 1 pt = 1 / 72 in


2.各种名词单位详解

px(pixel,像素)

图像的最小组成单元,美工PS和写网页的时候用得比较多,直观理解就是:
以前我们小时候看的黑白电视,如果你的眼睛离屏幕很近很近,不难看到屏幕
有一个个的点,这些点有个好听的名字,叫做像素点,黑白电视点的表现
形式只有黑白,半个字节4个位(1 byte = 8 bit)代表一个像素点,可以表现
2^4种颜色;后来的彩色电视则采用2个字节(16bit,ARGB)来保存像素点,所以
可以表示2^16 = 65536种颜色。


dp(dip,密度无关像素)

Density-independent pixel,抽象意义上的像素,与设备的实际物理像素点无关
可以保证在不同的像素密度的设备上显示相同的效果,Android独有的长度单位。
1dp表示在屏幕像素密度为160dpi的屏幕上,1dp = 1px
同理,在320dpi上,1dp = 2px,对了,官网上还有条公式:
px = dp * (dpi / 160)


sp(sip,独立比例像素)

scale-independent pixel,字体大小专用单位,会根据系统设置的字体大小进行
缩放,推荐使用12sp以上的字体(12sp以下太小),也不推荐用奇数和小数,容易造成
精度丢失问题


in(英寸)

1英寸大约是2.54cm,一般我们说手机多少寸就是这个单位。


手机外观尺寸

就是整个手机的尺寸,一般网上都有得查,比如我之前的手机:

当然,如果你对参数有怀疑的话可以自己用尺子量,要很精确的话可以用游标卡尺~


屏幕尺寸

屏幕对角线的长度,单位是英寸

计算公式如下:

对角线的平方 = 长的平方 + 宽的平方(对角线 * 对角线 = 长 * 长 + 宽 * 宽)
比如这里就是:对角线*对角线 = 4 *4 + 3 * 3 = 25;所以对角线就为5了,也就是
屏幕尺寸为5英寸;


分辨率(Resolution)

屏幕竖直方向与水平方向的像素个数,比如:1280*720 就说明屏幕的
竖直方向上有1280个像素点,而水平方向上有720个像素点。


屏幕像素密度(dpi,ppi)

dot per inch,简称屏幕密度,即每英寸有多少个像素点,屏幕密度值
越大,屏幕越清晰细致,这些参数可以从一些手机评测网站找到,比如下面
的魅族MX4 Pro:

他的屏幕密度为543ppi,也就是一英寸有543个像素点,另外这个参数我们
也可以自行计算,公式如下:

假设屏幕分辨率为:x * y,屏幕密度为s,屏幕尺寸为a * b,那么有
x * y = s * a * b


3.文字大小用sp的问题

官方文档:长度宽度用dp字体大小用sp,但是用sp的话,会有一个
问题:当用户修改系统字体大小的时候,字体大小会跟随着变化!如果我
们用的sp来修饰字体的话,当用户把系统字体调得很大,或者很小的时候,可
能会使我们的页面UI各种丑,个人还是建议使用dp来设置字体的大小,以
规避这个问题!


4.单位转换

  1. public class DensityUtil {
  2. /**
  3. * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
  4. */
  5. public static int dp2px(Context context, float dpValue) {
  6. final float scale = context.getResources().getDisplayMetrics().density;
  7. return (int) (dpValue * scale + 0.5f);
  8. }
  9. /**
  10. * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
  11. */
  12. public static int px2dp(Context context, float pxValue) {
  13. final float scale = context.getResources().getDisplayMetrics().density;
  14. return (int) (pxValue / scale + 0.5f);
  15. }
  16. /**
  17. * 将px值转换为sp值
  18. */
  19. public static int px2sp(Context context, float pxValue) {
  20. final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
  21. return (int) (pxValue / fontScale + 0.5f);
  22. }
  23. /**
  24. * 将sp值转换为px值
  25. */
  26. public static int sp2px(Context context, float spValue) {
  27. final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
  28. return (int) (spValue * fontScale + 0.5f);
  29. }
  30. }

5.获取屏幕尺寸与屏幕密度

  1. public class GetScreenParameter {
  2. //方法一:已过时,可使用,但不建议使用
  3. public static void getResolution1(Context mContext) {
  4. Display mDisplay = ((Activity) mContext).getWindowManager()
  5. .getDefaultDisplay();
  6. int W = mDisplay.getWidth();
  7. int H = mDisplay.getHeight();
  8. Log.i("getResolution1", "Width = " + W + "px");
  9. Log.i("getResolution1", "Height = " + H + "px");
  10. }
  11. //方法二:通过getWindowManager来获取屏幕尺寸的
  12. public static void getResolution2(Context mContext) {
  13. DisplayMetrics mDisplayMetrics = new DisplayMetrics();
  14. ((Activity) mContext).getWindowManager().getDefaultDisplay()
  15. .getMetrics(mDisplayMetrics);
  16. int W = mDisplayMetrics.widthPixels;
  17. int H = mDisplayMetrics.heightPixels;
  18. // 屏幕密度(0.75 / 1.0 / 1.5)
  19. float density = mDisplayMetrics.density;
  20. // 就是屏幕密度 * 160而已,屏幕密度DPI(120 / 160 / 240)
  21. int densityDpi = mDisplayMetrics.densityDpi;
  22. Log.i("getResolution2", "Width = " + W + "px");
  23. Log.i("getResolution2", "Height = " + H + "px");
  24. Log.i("getResolution2", "density = " + density);
  25. Log.i("getResolution2", "densityDpi = " + densityDpi);
  26. }
  27. //方法三:通过getResources来获取屏幕尺寸的,大部分用这个
  28. public static void getResolution3(Context mContext) {
  29. DisplayMetrics mDisplayMetrics = new DisplayMetrics();
  30. mDisplayMetrics = mContext.getResources().getDisplayMetrics();
  31. int W = mDisplayMetrics.widthPixels;
  32. int H = mDisplayMetrics.heightPixels;
  33. float density = mDisplayMetrics.density;
  34. int densityDpi = mDisplayMetrics.densityDpi;
  35. Log.i("getResolution3", "Width = " + W + "px");
  36. Log.i("getResolution3", "Height = " + H + "px");
  37. Log.i("getResolution3", "density = " + density);
  38. Log.i("getResolution3", "densityDpi = " + densityDpi);
  39. }
  40. }

PS:对于屏幕密度很低的小屏手机,比如240*320,计算出来的尺寸,可能为:320*427
原因是:没有设置多分辨率支持的话,Android系统会将240x320的低密度(120)尺寸
转换为中等密度160dpi对应的尺寸,如果你想获得正确的物理尺寸,需要在
AndroidManifest.xml里添加下述代码:

  1. <supports-screens
  2. android:smallScreens="true"
  3. android:normalScreens="true"
  4. android:largeScreens="true"
  5. android:resizeable="true"
  6. android:anyDensity="true"/>

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注