So where do you begin when designing for multiple screens? One approach is to work in the base standard (medium size, MDPI) and scale it up or down for the other buckets. Another approach is to start with the device with the largest screen size, and then scale down and figure out the UI compromises you'll need to make on smaller screens.
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
{{{
在TypedValue.java里面存在如下
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;
}
而在DisplayMetrics.java里面
public void setToDefaults() {
widthPixels = 0;
heightPixels = 0;
density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
densityDpi = DENSITY_DEVICE;
scaledDensity = density;
xdpi = DENSITY_DEVICE;
ydpi = DENSITY_DEVICE;
noncompatWidthPixels = 0;
noncompatHeightPixels = 0;
}
public static final int DENSITY_DEVICE = getDeviceDensity();
private static int getDeviceDensity() {
// qemu.sf.lcd_density can be used to override ro.sf.lcd_density
// when running in the emulator, allowing for dynamic configurations.
// The reason for this is that ro.sf.lcd_density is write-once and is
// set by the init process when it parses build.prop before anything else.
return SystemProperties.getInt("qemu.sf.lcd_density",
SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT));
}
而且scaledDenisity
在Resources.java的updateConfiguration函数里
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
--------------------------
scaledDensity = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
xdpi = DENSITY_DEVICE;
--------------------------
DENSITY_DEFAULT = DENSITY_MEDIUM = 160;
dp,dip,sp均为android中的概念。
dp即dip(Density-independent pixel),抽象概念,在每英寸160像素(DPI=160)的屏幕上1dp=1px。
So where do you begin when designing for multiple screens? One approach is to work in the base standard (medium size, MDPI) and scale it up or down for the other buckets. Another approach is to start with the device with the largest screen size, and then scale down and figure out the UI compromises you'll need to make on smaller screens.
即一个android程序提供多套图片资源和配置文件就可以适应各种屏幕,比如一个程序定义一行四个按钮,每个按钮宽60dp, 我的手机galaxy nexus的4.65寸1280*720屏幕中(密度320DPI,1dp=2px),调用的每个图片都是宽120像素的,而在htc的3.8寸800*480的屏幕中(密度240DPI,1dp=1.5px)同样一行显示4个图片,每个图片宽90像素。由于长宽比例不同,实际效果会有长或宽的间隙不同的问题,估计可以在布局文件中调整,下面是官方文档中的定义。
A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
我只知道px是像素
dip: device independent pixels(设备独立像素). 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。
px: pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多。
pt: point,是一个标准的长度单位,1pt=1/72英寸,用于印刷业,非常简单易用;
sp: scaled pixels(放大像素). 主要用于字体显示best for textsize。
由此,根据 google 的建议,TextView 的字号最好使用 sp 做单位,而且查看
TextView
的源码可知 Android 默认使用 sp 作为字号单位。
{{{ 在TypedValue.java里面存在如下 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; } 而在DisplayMetrics.java里面 public void setToDefaults() { widthPixels = 0; heightPixels = 0; density = DENSITY_DEVICE / (float) DENSITY_DEFAULT; densityDpi = DENSITY_DEVICE; scaledDensity = density; xdpi = DENSITY_DEVICE; ydpi = DENSITY_DEVICE; noncompatWidthPixels = 0; noncompatHeightPixels = 0; } public static final int DENSITY_DEVICE = getDeviceDensity(); private static int getDeviceDensity() { // qemu.sf.lcd_density can be used to override ro.sf.lcd_density // when running in the emulator, allowing for dynamic configurations. // The reason for this is that ro.sf.lcd_density is write-once and is // set by the init process when it parses build.prop before anything else. return SystemProperties.getInt("qemu.sf.lcd_density", SystemProperties.getInt("ro.sf.lcd_density", DENSITY_DEFAULT)); } 而且scaledDenisity 在Resources.java的updateConfiguration函数里 mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; case COMPLEX_UNIT_PX: return value; case COMPLEX_UNIT_SP: return value * metrics.scaledDensity; case COMPLEX_UNIT_PT: return value * metrics.xdpi * (1.0f/72); -------------------------- scaledDensity = DENSITY_DEVICE / (float) DENSITY_DEFAULT; xdpi = DENSITY_DEVICE; -------------------------- DENSITY_DEFAULT = DENSITY_MEDIUM = 160;}}}