1.密度(density)
①屏幕密度的计算
手机像素密度(density)实际上是以单位英寸160个像素作为参考标准,主要密度有0.75,1,1.5,2和3,当密度为2时就表示1英寸有320个像素,Android中通过代码可以获取到屏幕的像素值和密度,根据这些值就
可以反向算出屏幕的物理尺寸:屏幕尺寸 = 屏幕对角线的像素值 / (密度*160) = [(长的平方+宽的平方)开根号] / (密度*160) --> dp = px / (density / 160)
简单来说:屏幕密度(density) = 对角线的像素值(px) / 屏幕大小(inch)
比如现在的htc one,屏幕分辨率1920*1080,屏幕大小4.7inch(英寸),对应的密度为:Math.sqrt(1920*1920+1080*1080) / 4.7 = 468.7<480,是xhdpi
②密度分类
低密度(120) ldpi : low-density --- QVGA和WQVGA
中密度(160) mdpi : medium-density --- HVGA Android的屏幕密度是以160为基准的,此时:1dp=1px
高密度(240) hdpi : high-density --- WVGA
超高密度(320) xhdpi : extra-high-density
极高密度(480) xxhdpi : extra-extra-high-density
③密度直观比较图
这是最新的官网设备密度截图,从图中可知:以MDPI(160)为标准参考值1,HDPI,XHDPI,XXHDPI分别为1.5,2,3。UI设计时,也可以此为参考,如设计一个中等密度(medium)屏幕的图标大小为48×48像素,
由low:medium:high:extra high:extra extra high = 3:4:6:8:12,这样的比值关系,得出:低密度(low)屏幕的图片大小应为36×36像素,高密度(high)屏幕的为72×72像素,超高密度(extra high)屏幕为
96×96像素,极高密度(extra-extra-high)屏幕为144×144像素。
由上图可知之前的低密度的LDPI(0.75x)没有出现在图中,取而代之的是XXHDPI,正所谓,长江后浪推前浪,前浪被拍死在沙滩上。。。
④各ui控件像素值
Icon Type | Standard Asset Sizes (in Pixels), for Generalized Screen Densities | ||
| Low density screen (ldpi) | Medium density screen (mdpi) | High density screen (hdpi) |
Launcher | 36 x 36 px | 48 x 48 px | 72 x 72 px |
Menu | 36 x 36 px | 48 x 48 px | 72 x 72 px |
Status Bar | 24 x 24 px | 32 x 32 px | 48 x 48 px |
Tab | 24 x 24 px | 32 x 32 px | 48 x 48 px |
Dialog | 24 x 24 px | 32 x 32 px | 48 x 48 px |
List View | 24 x 24 px | 32 x 32 px | 48 x 48 px |
⑤代码中获取手机密度
public class TestPhoneDensity extends AndroidTestCase {
public void testDensity() throws Exception {
DisplayMetrics metric = new DisplayMetrics();
WindowManager wm = (WindowManager) getContext().getSystemService(
Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(metric);
int densityDpi = metric.densityDpi;
System.out.println("densityDpi:" + densityDpi);
}
}
获取设备详细信息
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 屏幕宽度(像素)
int height = metric.heightPixels; // 屏幕高度(像素)
float density = metric.density; // 屏幕密度(0.75/1.0/1.5/2.0/3.0)
int densityDpi = metric.densityDpi; // 屏幕密度DPI(120/160/240/320/480)
double diagonalPixels = Math.sqrt(Math.pow(width, 2) + Math.pow(height, 2)); // 屏幕对角线长度(像素)
double screenSize = diagonalPixels / (160 * density); // 屏幕尺寸
System.out.println("宽:"+width+", 高:"+height+", 密度:"+density+"("+densityDpi+")"+"\n"+"对角线像素值:"+diagonalPixels+", 屏幕大小:"+screenSize+"英寸");
2.屏幕尺寸和密度
3.适配多种屏幕
①在manifest清单文件里定义程序支持的屏幕类型,相应代码如下:
<supports-screens android:resizeable=["true"| "false"]
android:smallScreens=["true" | "false"] //是否支持小屏
android:normalScreens=["true" | "false"] //是否支持中屏
android:largeScreens=["true" | "false"] //是否支持大屏
android:xlargeScreens=["true" | "false"] //是否支持超大屏
android:anyDensity=["true" | "false"] //是否支持多种不同密度的屏幕
android:requiresSmallestWidthDp=”integer”
android:compatibleWidthLimitDp=”integer”
android:largestWidthLimitDp=”integer”/>
<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:xlargeScreens="true"
android:anyDensity="true"
android:resizeable="true"/>
②对不同大小的屏幕提供不同的drawable,layout,values
res/drawable/my_drawable.png //默认
res/drawable-ldpi/my_drawable.png
res/drawable-mdpi/my_drawable.png
res/drawable-land-mdpi/my_drawable.png //横向
res/drawable-hdpi/my_drawable.png
res/drawable-xhdpi/my_drawable.png
res/drawable-xhhdpi/my_drawable.png
res/drawable-nodpi/my_drawable.png //平板
res/drawable-hdpi-800x480/my_drawable.png //给指定分辨率做适配
res/drawable-hdpi-854x480/my_drawable.png
res/drawable-sw600dp-mdpi/my_drawable.png
res/drawable-sw600dp-hdpi/my_drawable.png
res/drawable-sw600dp-xdpi/my_drawable.png
res/drawable-sw600dp-nodpi/my_drawable.pngres/layout/my_layout.xml //默认(放一些通用布局xml文件,比如界面中顶部和底部的布局,不会随着屏幕大小变化)
res/layout-land/my_layout.xml
res/layout-port/my_layout.xml
res/layout-ldpi/my_layout.xml
res/layout-mdpi/my_layout.xml
res/layout-hdpi/my_layout.xml
res/layout-land-ldpi/my_layout.xml
res/layout-land-mdpi/my_layout.xml
res/layout-land-hdpi/my_layout.xml
res/layout-small/my_layout.xml //屏幕尺寸小于3英寸左右的布局
res/layout-normal/my_layout.xml //屏幕尺寸小于4.5英寸左右
res/layout-large/my_layout.xml //4英寸-7英寸之间
res/layout-xlarge/my_layout.xml //7-10英寸之间
res/layout-xlarge-land/my_layout.xml //横屏
res/layout-sw600dp/my_layout.xml //sw<N>dp表示这个layout文件夹下面的布局文件只有在设备短边的最小宽为N时才加载~smallestWidth
res/layout-sw600dp-port/my_layout.xml //竖屏下最小为600的宽度
res/layout-w600dp/my_layout.xml //固定为600的宽度
res/layout-sw720dp/my_layout.xmlres/values/dimens.xml //默认
res/values-lhdpi/dimens.xml
res/values-mdpi/dimens.xml
res/values-hdpi/dimens.xml
res/values-xhdpi/dimens.xml
res/values-xhhdpi/dimens.xml
res/values-sw600dp/dimens.xml //同上
res/values-sw720dp/dimens.xml
res/values-nodpi-1280x800/dimens.xml //1280x800分辨率的平板(nodpi用于存放不管宿主屏幕密度如何都不进行缩放的资源)
res/values-large-land/dimens.xml //横向
res/values-large-port/dimens.xml //竖直方向
从以上文件夹名称不难发现规律:
一类是根据dpi屏幕密度划分(ldpi,mdpi,hdpi,xhdpi,xxhdpi,nodpi),一类是根据屏幕尺寸划分(small,normal,large,xlarge,1280x800-可自定义尺寸,sw<N>dp),这两类中又可细分成横屏和竖屏。
对于根据dpi屏幕密度划分的横竖屏:xxx-land-ldpi,对于根据屏幕尺寸划分的横竖屏:xxx-small-land,另外较为复杂的:密度和尺寸混用:xxx-sw600dp-hdpi
-----------更新,看了官网的文档,才发觉以上的总结不过是冰山一角,以下是完整版
MCC and MNC | Examples:mcc310,mcc310-mnc004,mcc208-mnc00.etc. |
Language and region | Examples:en,fr,en-rUS,fr-rFR,fr-rCA.etc. |
Layout Direction | ldrtl,ldltr |
smallestWidth | sw<N>dp,Examples:sw320dp,sw600dp,sw720dp.etc. |
Available width | w<N>dp,Examples:w720dp,w1024dp.etc. |
Available height | h<N>dp,Examples:h720dp,h1024dp.etc. |
Screen size | small,normal,large,xlarge |
Screen aspect | long,notlong |
Screen orientation | port,land |
UI mode | car,desk,television,appliance |
Night mode | night,notnight |
Screen pixel density (dpi) | ldpi,mdpi,hdpi,xhdpi,nodpi,tvdpi |
Touchscreen type | notouch,finger |
Keyboard availability | keysexposed,keyshidden,keyssoft |
Primary text input method | nokeys,qwerty,12key |
Navigation key availability | navexposed,navhidden |
Primary non-touch navigation method | nonav,dpad,trackball,wheel |
Platform Version (API level) | Examples:v3,v4,v7.etc. |
4.固定显示方向
在activity节点或是application节点下配置以下参数,表示屏幕方向固定为竖直方向或是横向,不随着传感器的变化而比变化。
android:screenOrientation="portrait" //竖直方向
android:screenOrientation="landscape" //横向
android:screenOrientation="sensor" //表示屏幕随着重力感应的方向变化而变化<即使重力感应没有开启>
5.Android各种屏幕分辨率(VGA、HVGA、QVGA、WQVGA、WVGA、FWVGA)
VGA:Video Graphics Array,即:显示绘图矩阵,相当于640×480 像素
HVGA:Half-size VGA,即:VGA的一半,分辨率为480×320,像三星盖世Ace S5830就是使用这分辨率
QVGA:Quarter VGA,即:VGA的四分之一,分辨率为320×240,一般用于小屏手机 像三星盖世Mini S5570就是使用这分辨率
WQVGA:Wide Quarter VGA,即:扩大的QVGA,分辨率比QVGA高,比VGA低,一般是:400×240,480×272
WVGA:Wide Video Graphics Array,即:扩大的VGA,分辨率为800×480像素,像三星i9000就是使用这分辨率
FWVGA:Full Wide VGA ,数码产品屏幕材质的一种,VGA的另一种形式,比WVGA分辨率高,别名 : Full Wide VGA, ,其分辨 率为854×480象素(16:9)
常见的分辨率
标屏 | 分辨率 | 宽屏 | 分辨率 |
QVGA | 320×240 | WQVGA | 400×240 |
VGA | 640×480 | WVGA | 800×480 |
SVGA | 800×600 | WSVGA | 1024×600 |
XGA | 1024×768 | WXGA | 1280×768/1280×800/1280*960 |
SXGA | 1280×1024 | WXGA+ | 1440×900 |
SXGA+ | 1400×1050 | WSXGA+ | 1680×1050 |
UXGA | 1600×1200 | WUXGA | 1920×1200 |
QXGA | 2048×1536 | WQXGA | 2560×1536 |
| Low density (120), ldpi | Medium density (160), mdpi | High density (240), hdpi | Extra high density (320), xhdpi |
Smallscreen | QVGA (240x320) | | 480x640 | |
Normalscreen | WQVGA400 (240x400) WQVGA432 (240x432) | HVGA (320x480) | WVGA800 (480x800) WVGA854 (480x854) 600x1024 | 640x960 |
Largescreen | WVGA800** (480x800) WVGA854** (480x854) | WVGA800* (480x800) WVGA854* (480x854) 600x1024 | | |
Extra Largescreen | 1024x600 | WXGA (1280x800)† 1024x768 1280x768 | 1536x1152 1920x1152 1920x1200 | 2048x1536 2560x1536 2560x1600 |
6.代码中写控件并设置宽高
①首先获取当前屏幕的宽高度,因为屏幕的宽高使用频率较高,且一般为不变常量,所以可以定义常量类保存当前屏幕的宽高
public class Constant {
public static int DISPLAY_WIDTH; //屏幕宽度
public static int DISPLAY_HEIGHT; //屏幕高度
}
在第一个Activity启动的时候,获取这两个值
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
Constant.DISPLAY_WIDTH = displayMetrics.widthPixels;
Constant.DISPLAY_HEIGHT = displayMetrics.heightPixels;
在代码中根据屏幕的宽高动态的设置控件的宽高
LayoutParams blueParams = new LayoutParams(
(int) (Constant.DISPLAY_WIDTH * 0.2f + 0.5f),
(int) (Constant.DISPLAY_HEIGHT * 0.2f + 0.5f));
bt_blue.setLayoutParams(blueParams);
bt_blue.setBackgroundResource(R.color.blue);
LayoutParams purpleParams = new LayoutParams(
(int) (Constant.DISPLAY_WIDTH * 0.4f + 0.5f),
(int) (Constant.DISPLAY_HEIGHT * 0.2f + 0.5f));
bt_purple.setLayoutParams(purpleParams);
bt_purple.setBackgroundResource(R.color.purple);
LayoutParams greenParams = new LayoutParams(
(int) (Constant.DISPLAY_WIDTH * 0.6f + 0.5f),
(int) (Constant.DISPLAY_HEIGHT * 0.2f + 0.5f));
bt_green.setLayoutParams(greenParams);
bt_green.setBackgroundResource(R.color.green);
LayoutParams orangeParams = new LayoutParams(
(int) (Constant.DISPLAY_WIDTH * 0.8f + 0.5f),
(int) (Constant.DISPLAY_HEIGHT * 0.2f + 0.5f));
bt_orange.setLayoutParams(orangeParams);
bt_orange.setBackgroundResource(R.color.orange);
LayoutParams redParams = new LayoutParams(
(int) (Constant.DISPLAY_WIDTH * 1.0f + 0.5f),
(int) (Constant.DISPLAY_HEIGHT * 0.2f + 0.5f));
bt_red.setLayoutParams(redParams);
bt_red.setBackgroundResource(R.color.red);
7.译文
http://developer.android.com/training/multiscreen/screensizes.html
中文翻译:http://bbs.9ria.com/thread-191031-1-1.html
8.Supporting Different Screen Sizes
①Use "wrap_content" and "match_parent"
②Use RelativeLayout
③Use Size Qualifiers
④Use the Smallest-width Qualifier
⑤Use Layout Aliases
⑥Use Orientation Qualifiers
⑦Use Nine-patch Bitmaps
http://developer.android.com/training/multiscreen/screensizes.html
http://www.androidlearner.net/android-multi-screen-about.html (android – 多屏幕适配相关)
framework调用链)
(Android各种屏幕分辨率(VGA、HVGA、QVGA、WQVGA、WVGA、FWVGA) 详解)
(android:屏幕自适应)
(Android手机分辨率基础知识(DPI,DIP计算))
http://developer.android.com/guide/practices/screens_support.html
http://developer.android.com/guide/topics/resources/providing-resources.html