07、屏幕适配(重点待续)

浪尽此生 提交于 2020-01-23 06:10:06

一、Android碎片化介绍

由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,导致Android碎片化问题。

在2012年,OpenSingnalMaps(OSM)发布第一份Android碎片化报告,统计数据表明:

  • 2012年,支持Android的设备共有3997种。
  • 2013年,支持Android的设备共有11868种。
  • 2014年,支持Android的设备共有18796种。

下面的图片所显示的内容充分说明当今Android系统碎片化问题的严重性,每一种矩形都代表一种Android设备。

image

随着支持Android系统的设备的增多,设备碎片化、品牌碎片化、系统碎片化、传感器碎片化和屏幕碎片化的程度也在不断的加深。

下图是2014年初,友盟统计的占比5%以上的6个主流分辨率:

1ecd31db-36b5-4c53-8216-c7c41ed31710

所以,我们只要尽量适配这几种分辨率,就可以在大部分的手机上正常运行。

二、常用单位和换算

1.1、什么是屏幕尺寸、屏幕分辨率、屏幕像素密度

1、屏幕尺寸指屏幕的对角线的长度,单位是英寸

1 英寸 = 2.54 厘米

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

2、屏幕分辨率是指在横纵向上的像素点数,单位是px

1 px = 1 像素点

一般以纵向像素 * 横向像素,如1960 * 1080。

3、像素密度是指每英寸上的像素点数,单位是dpi,屏幕像素密度与屏幕尺寸和屏幕分辨率有关。

1.2、什么是px、dp、dip、dpi、sp?

px是像素单位,多数情况下,比如ui设计或Android原生API都会以px作为统一的计量单位,像是获取屏幕宽高等。

dip和dp是一个意思,都是Density Independent Pixels的缩写,即密度无关像素,上面我们说过,dpi是屏幕像素密度。

dp和px换算公式:

pixs = dips * (densityDpi / 160)
dips = (pixs * 160) / densityDpi 

dp与px转换的方法:

public static int dip2px(Context context, float dipValue){ 
  final float scale = context.getResources().getDisplayMetrics().density; 
  return (int)(dipValue * scale + 0.5f); 
 } 

public static int px2dip(Context context, float pxValue){ 
  final float scale = context.getResource().getDisplayMetrics().density; 
  return (int)(pxValue / scale + 0.5f); 
 } 

1.3、什么是mdpi、hdpi、xdpi、xxdpi?

其实还有一个ldpi,但是随着移动设备配置的不断升级,这个像素密度的设备已经很罕见,所以不需要考虑

mdpi、hdpi、xdpi、xxdpi用来修饰Android中的drawable文件夹及values文件夹,用来区分不同像素密度下的图片和dimen值。

在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面:

92e380de-b4ff-4cab-9054-05c38158a81f

Drawable目录默认是中等密度(drawable-mdpi)

nohdpi表示所有密度资源,无论什么密度屏幕都会适配。

drawable-tvdpi介于mdpi~hdpi 约213dpi 主要应用在电视。

在Android的设计规范中,DPI分成了5个档次:MDPI,HDPI,XHDPI,XXHDPI,XXXHDPI,它们的比例是 2:3:4:6:8,

规定以160dpi为基准,1dip = 1px,如果密度是320dpi,则1dip = 2px,以此类推。

1.4、屏幕适配

在Android的设计规范中

  • 根据屏幕大小把屏幕分成了4类:Small,Normal,Large,Extra Large。
  • 根据屏幕的密度把屏幕密度划分为4类:Low,Medium,High,Extra High。

编写布局时,尽量使用match_parent或wrap_content,尽量使用weight权重来对屏幕进行划分。并使用RelativeLayout,禁用AbsoluteLayout。

1、根据屏幕密度进行划分

通常来说,Android通过缩放使得APP可以适应屏幕大小,但是对于一些特殊情况,我们可以提供更佳的布局使得体验更好。

例如,在大屏幕设备,可以通过调整UI组件的位置和大小使屏幕的空间可以得到充分利用。对于小设备,就只需要调整UI组件的大小就行。

布局常用的大小有small,normal,large和x-large,可以根据需要选择布局的类型进行配置。
常用的布局配置如下:

res/layout/layout.xml
res/layout-small/layout.xml
res/layout-large/layout.xml
res/layout-large-land/layout.xml

所以按照dp来划分如下:

small    426dp x 320dp
normal     470dp x 320dp
large        640dp x 480dp
xlarge      960dp x 720dp

这种方式在Android3.2之后已经不再推荐使用。

2、使用布局限定符

在android3.2以前,所有的资源文件都有相应的xhdpi,hdpi,mdpi,ldpi四种文件来对应,android3.2以后,为了提供更精准的对布局文件的控制,可以通过为资源文件(res目录下文件)
增加后缀来指定该文件夹里的xml布局文件或color.xml,string.xml是为哪种大小的屏幕使用。

(a) 第一种 layout-sw720dp

layout-sw720dp, values-sw720dp
sw = smallwidth,当你所有屏幕的最小宽度都大于720dp时,屏幕就会自动到带sw720dp后缀的资源文件里去寻找相关资源文件,这里的最小宽度是指屏幕宽高的较小值;

(b) 第二种 layout-w720dp

layout-w720dp, values-w720dp
这种命名跟第一种非常的像,相同之处在于:当你所有屏幕的最小宽度都大于720dp时,屏幕就会自动到带sw720dp后缀的资源文件里去寻找相关资源文件;
不同之处在于:屏幕横向纵向改变;
屏幕会根据变化后的实际情况去找layout-w720dp,当屏幕竖向的时候,x方向是宽,当屏幕横向的时候,y方向是宽;
但是layout-sw720dp一开始就理性地认定了屏幕的高宽,由始至终认定小边就是宽,大边就是高,就算屏幕变化了也不改变这个事实;从命名也看出smallwidth,小边是宽。

(c) 第三种 layout-h720dp
layout-h720dp, values-h720dp
这个后缀没有s,随着屏幕横纵向的变化,屏幕高度也会变化,根据变化后的高度值来判断是否使用layout-h720dp;
但有没有发现这种方式很少使用,因为有一个标题要吃掉底部状态栏所占有的高度(要吃掉48个像素),
由此google官方文档建议尽量少使用这种方式。

(d) 第四种 layout-land-1024x720
layout-land-1024x720,values-land-1024x720
这个是固定为横向的布局使用,如果是纵向:layout-port-1024x720;这种固定分辨率适用于固定适配特殊设备的情况。

(e) 第五种 layout-1024x720
固定的尺寸,适用罕见尺寸,或者需要微调的机器;
还有一些比较奇葩的分辨率(比如魅族MX3的分辨率是1800x1080,MX4的1920x1152,MX4 pro的2560x1536,山寨华为的卖的比较火的mediapad的是1280*800),

为了能够准备配置到需要特定的命名方式:
layout-1800x1080
layout-1920x1152
layout-2560x1536
layout-1280*800

关于扣掉底部状态栏所占有的高度48个像素的来由:

  • android3.0之前,适配指定分辨率,将layout文件夹命名:layout  layout-1024x768   layout-1024x600   layout-1280x768
  • android3.0以后,需将高度减去48像素,即底部状态栏的高度:layout  layout-1024x720   layout-1024x552   layout-1280x720
  • 横屏版本的话,中间加上land,例如: layout-land-1024x720;

所有情况大约如下:

系统读取资源是有顺序的,只需要适配比较特殊的情况,不需要特殊做适配的,只需要放到layout默认目录下,系统读取不到的情况回到默认路径下读取;

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!