android系统中DP和SP的转化:
1.首先分析TypedValue.java
可以调用以下代码获得dp的值
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,getResources().getDisplayMetrics());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.0f/72); case COMPLEX_UNIT_IN: return value * metrics.xdpi; case COMPLEX_UNIT_MM: return value * metrics.xdpi * (1.0f/25.4f); } return 0; }
2.接着分析Resource.java
在Resoucrce中会调用 mMetrics.setToDefaults();设置DisplayMetrics的density的值
1 public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config, 2 CompatibilityInfo compatInfo, IBinder token) { 3 mAssets = assets; 4 mMetrics.setToDefaults(); 5 if (compatInfo != null) { 6 mCompatibilityInfo = compatInfo; 7 } 8 mToken = new WeakReference<IBinder>(token); 9 updateConfiguration(config, metrics);10 assets.ensureStringBlocks();11 }12 13 public void setToDefaults() {14 widthPixels = 0;15 heightPixels = 0;16 density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;17 densityDpi = DENSITY_DEVICE;18 scaledDensity = density;19 xdpi = DENSITY_DEVICE;20 ydpi = DENSITY_DEVICE;21 noncompatWidthPixels = widthPixels;22 noncompatHeightPixels = heightPixels;23 noncompatDensity = density;24 noncompatDensityDpi = densityDpi;25 noncompatScaledDensity = scaledDensity;26 noncompatXdpi = xdpi;27 noncompatYdpi = ydpi;28 }29 30 DENSITY_DEFAULT默认值为160,在系统中可以更改这个值31 public static int DENSITY_DEVICE = getDeviceDensity();32 33 private static int getDeviceDensity() {34 35 return SystemProperties.getInt("qemu.sf.lcd_density",36 SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));37 }38 39 40 41 DENSITY_DEVICE是通过计算屏幕分辨率得出的,计算方式如下:
ro.sf.lcd_density的属性值:
-------------------------------
对于分辨路为720*1280 5.5寸:
ro.sf.lcd_density = 320
320/160 = 2
计算方式:720*1280 5.5寸 1280*1280+720*720 = 1648.6047/5.5 = 267.0190(取320)
--------------------------------------------------------------------
对于分辨路为1080*1920 5.5寸::
ro.sf.lcd_density = 320
480/160 = 3:
计算方式:1080*1920 5.5寸 2202.90707/5.5 = 400.5285(取480)
系统会将计算出的DPI转化成(120 160 240 320 480)
4.
通过以上分析可知
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
getResources().getDisplayMetrics());
=20*getProp("ro.sf.lcd_density")/DENSITY_DEFAULT
= 20*getProp("ro.sf.lcd_density")/160
5在实际编程中,我们常用的dp和px转化代码是:区别就在于将float转化成了int,仅此而已
/** * 根据手机的分辨率从 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); }