Android多屏幕适配

参考

http://developer.android.com/guide/practices/screens_support.html

问题:  
测试时,发现应用在不同的显示器上显示效果不同(部分文本不能显示完全),自然想到屏幕适配的问题。    
按照思路整理如下:    
 

详解概念

(1)屏幕尺寸
屏幕尺寸指屏幕的对角线的长度,单位是英寸(inch),1英寸=2.54厘米

比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等。

(2)屏幕分辨率(Resolution)
屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素,如1960*1080。

(3)屏幕像素密度(density)
屏幕像素密度是指density 为每平方英寸中的像素数量,屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

(4)  Density-independent pixel (dp)独立像素密度。标准是160dip.即1dp对应1个pixel,计算公式如:px = dp * (dpi / 160),屏幕密度越大,1dp对应 的像素点越多。

Google的官方说明是这样的:
  Density-independent pixel (dp) 
  A virtual pixel unit that you should use when defining UI layout, to express layout dimensions or position in a density-independent way. 

定义UI布局时应使用的虚拟像素单元,用于以与密度无关的方式表示布局尺寸或位置。
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.

与密度无关的像素相当于160 dpi屏幕上的一个物理像素,这是系统为“中等”密度屏幕假定的基线密度。在运行时,系统根据正在使用的屏幕的实际密度,根据需要透明地处理任何DP单元的缩放。dp单元到屏幕像素的转换非常简单:px=dp*(dpi/160)。例如,在240 dpi屏幕上,1 dp等于1.5物理像素。在定义应用程序的UI时,应该始终使用DP单元,以确保在不同密度的屏幕上正确显示UI。

就是说在160dpi的屏幕上,1dip=1px。
  它跟屏幕密度有关,如果屏幕密度大,1dip代表的px就多,比如在320dpi的屏幕上,1dip=2px。

(5)px、dpi、dp和dip、sp

a.  px我们应该是比较熟悉的,前面的分辨率就是用的像素为单位,大多数情况下,比如UI设计、Android原生API都会以px作为统一的计量单位,像是获取屏幕宽高等。

b.   dpi是屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi,那么在这种情况下,dp和px如何换算呢?在Android中,规定以160dpi为基准(320*480),1dip=1px,如果密度是320dpi,则1dip=2px,以此类推,关系式:px = dp * (dpi / 160)。

假如同样都是画一条320px的线,在480*800分辨率手机上显示为2/3屏幕宽度,在320*480的手机上则占满了全屏,如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。这也是为什么在Android开发中,写布局的时候要尽量使用dp而不是px的原因。

 c.  dip和dp是一个意思,都是Density Independent Pixels的缩写,即密度无关像素;

d.   sp,即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行放缩,是设置字体大小的御用单位。

 

 

dp和px转换

dp=dx/(dpi/160)

计算dpi

以5.5寸、1920 * 1080的手机为例:

5.5寸是指手机对角线的长度,分辨率是1920 * 1080,也就是知道长像素是1920宽像素是1080,那么对角线多长呢,其实就是求斜边的长度: 1920^2+1080^2=2202^2(勾股定理)

所以 dpi=2202/5.5=400

Android多屏幕适配,同理

dpi=1920/a=1080/b,其中a,b分别是宽长度,高长度,单位inch。

height和width即为长宽的像素,平方和即为对角线的像素个数,size即我们常说的5寸手机、4寸手机中的5和4,即对角线的长度
 

计算 独立像素密度density

density=dpi/160


(二) 屏幕的分类(size & density)    
1, 以总像素数分,文本的size等都要改,如下图所示

Android多屏幕适配

每一个分类都有其最小分辨率,如下,可根据分辨率划分种类:


Android多屏幕适配

2, 以屏幕密度分,提供不同的图片如下图所示

Android多屏幕适配

Note1:匹配以上面两种为参考。  
Note2:还有专为水平(landscape)和竖直(portrait)两种,使用的少,在此不赘述。    

(三) Android寻找最佳资源原理    
1, 排除与设备设置不符合的资源    
2, 根据限定词(qualifier)的优先级,按照顺序查找    
3, 在限定词下,是否存在资源路径    
4, 排除不包含在限定词中的资源路径    
5   继续执行不同的限定词查找,直到找到相应的资源    
如下图所示:

Android多屏幕适配    
(四) 项目步骤:    
1, manufest中配置    
<supports-screens
 android:anyDensity="true"
 android:largeScreens="true"
 android:normalScreens="true"
 android:smallScreens="true"
 android:xlargeScreens="true" />
2, 新建对应的资源文件夹    
A, Layout    
例如,我现在有三个显示器分辨率:    
分别为1280*720,1024*768,1200*690
根据以上最低分辨率的要求,分为xlarge和large两类,新建两个文件夹,如下:    
如下图所示:

Android多屏幕适配

B, Drawable  
如下图所示:

Android多屏幕适配

在drawable中,以mdpi为标准(即160dpi)。比例保持为3:4:5:6,如下图所示:

Android多屏幕适配