Android屏幕的适配,是每一个Android工程师在开发过程中都会遇到的恼人的难题,其实我们看一下android设备就知道了,千奇百怪,万种变化,在适配的时候就有点怵.
屏幕适配的原因:
由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,修改成他们想要的样子。而随着支持Android系统的设备(手机、平板、电视、手表)的增多,设备碎片化、品牌碎片化、系统碎片化、传感器碎片化和屏幕碎片化的程度也在不断地加深
重要概念:
1. 屏幕尺寸、屏幕分辨率、屏幕像素密度
屏幕尺寸:屏幕对角线长度,单位是英寸,我们常说的多少多少寸,比如4.7存手机、5.7存手机,指的就是这个。
屏幕分辨率:如 1920×1080,是指在手机屏幕的像素点的个数,单位是px,1px = 1 像素点,一般是纵向像素× 横向像素,意味着高有1920 个像素点,宽有1080 个像素点。表示物理屏幕区域内像素点的总和(切记:跟屏幕适配没有任何关系),因为我们既可以把1920*1080的分辨率做到4.0的手机上,也可以把这个分辨率做到5.0英寸的手机上面,如果分辨率相同,手机屏幕越小越清晰
屏幕像素密度:是指每英寸上的像素点数,单位是dpi(dotper inch)。像素密度和屏幕尺寸和屏幕分辨率有关,它是由对角线的像素点数除以屏幕的大小得到的,关系如下:
屏幕像素密度算法
(单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。)
dp、dip、dpi、sp、px(pix)
dp:是Android 特有的,意为密度无关像素,Google 发布的BASELINE(基准线)为160,以此为基准。
dip:Density Independent Pixels,同dp一个意思,目前废弃了,一般都写dp。
dpi:即为屏幕像素密度的单位
sp:Scale-IndependentPixels的缩写,可以根据文字大小首选项自动进行缩放。Google推荐我们使用12sp以上的大小,通常可以使用12sp,14sp,18sp,22sp,为避免精度损失,建议最好不要使用奇数和小数。
px(pix):就是我们常说的像素,就是屏幕中最小的一个显示单元.不同设备显示的效果相同
mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi
一般都是采用以下几种解决方案:
解决方案看图:
适配相关术语:
分辨率(eg):480X800,1280X720。表示物理屏幕区域内像素点的总和。(切记:跟屏幕适配没有任何关系) 因为我们既可以把1280X720的分辨率做到4.0的手机上面。我也可以把1280X720的分辨率做到5.0英寸的手机上面,如果分辨率相同,手机屏幕越小越清晰。
px(pix):像素,就是屏幕中最小的一个显示单元。不同设备显示效果相同。
dpi(像素密度):即每英寸屏幕所拥有的像素数,像素密度越大,显示画面细节就越丰富。计算公式:像素密度=√{(长度像素数2+宽度像素数2)}/ 屏幕尺寸
(注:屏幕尺寸单位为英寸 例:分辨率为1280*720 屏幕宽度为6英寸 计算所得像素密度约等于245,屏幕尺寸指屏幕对角线的长度.)
dip: deviceindependent pixels ,设备独立像素。不同设备有不同的显示效果,这个和设备硬件有关。
屏幕适配方式:
- 图片适配
在我们的Android工程目录中有如下drawable/mipmap-*dpi目录,这些目录是用来适配不同分辨率手机的。
不同的目录,代表手机不同的像素密度:
以下是Android系统的适配策略:
Android应用在查找图片资源时会根据其分辨率自动从不同的文件目录下查找。如果在低分辨的文件目录中比如drawable-mdpi中没有图片资源,其他目录中都有,当我们将该应用部署到mdpi分辨率的手机上时,那么该应用会查找分辨率较高目录下的资源文件,如果较高分辨率目录下也没有资源则只好找较低目录中的资源了。
1.尺寸适配
跟drawable目录类似的,在Android工程的res目录下有values目录,这个是默认的目录,同时为了适配不同尺寸手机我们可以创建一个values-1280x720的文件夹,同时将dimens.xml文件拷贝到该目录下。
在dimens.xml中定义一个尺寸,如下图所示。
在values-1280x720目录中的dimens.xml中定义同样的尺寸名称,但是使用不同的尺寸,如下图所示。
当我们在布局文件中使用长或者宽度单位时,比如下图所示,应该使用@dimen/width来灵活的定义宽度。
- 布局适配-(这种适配几乎不常见)
跟values一样,在Android工程目录中layout目录也支持类似values目录一样的适配,在layout中我们可以针对不同手机的分辨率制定不同的布局,如下图所示。
权重适配(谷歌推荐)
在控件中使用属性android:layout_weight="1"可以起到适配效果,但是该属性的使用有如下规则: 只能用在线性控件中,比如LinearLayout。 竖直方向上使用权重的控件高度必须为0dp(Google官方的推荐用法) 水平方向上使用权重的控件宽度必须为0dp(Google官方的推荐用法)代码适配
在java代码中动态计算控件的宽度和高度。 注意:计算的宽度和高度,这里涉及到dp和px之间的转化:
说明一下dp代表什么意思? dip: deviceindependent pixels(设备独立像素)。不同设备有不同的显示效果,这个和设备硬件有关。这里指一个抽象意义上的像素,程序用它来定义界面元素。一个与密度无关,在逻辑尺寸上,与一个位于像素密度为160dpi的屏幕上的像素是一致的。
要把密度无关像素转换为屏幕像素可以用这样一个简单的公式:pixels=dips*(density/160)。
举个例子,在DPI为240的屏幕上,1个DIP等于1.5个物理像素。
代码中相互换算:
- 百分比适配
该适配一般对图片进行适配的。 比如:在同一张图片,在不同的设备中,按照图片的宽高比例,进行缩放显示。
- 获取图片的宽度和高度
- 计算图片的宽度和高度的比例
- 根据图片的比例,计算出图片的在设备中的显示的实际宽度和高度
关于切图数量的分析:
跟UI人员要求,对于主流的手机机型分辨率,选1至2套完整的一套图片(比如1920×1080分辨率是主流机型),这一套图必须是完整的,但是对于平铺整个界面的大图需要多切几套,比如说欢迎界面,帮助界面等之类的图片,针对于小图的话就只需要一套左右就够了,因为小图在屏幕上的稍微拉伸,人的视觉效果是很难感觉到的,在android studio图片目录结构中,编译工具找图的顺序是当找不到的时候,先往高分辨率,再往低分辨率找.
为什么我们要将对应分辨率的图片放入对应文件夹?(根据以下图片进行分析)
三星手机拍照有哪些bug?
摄像头拍照后图片数据有可能不能返回; 应该是onActivityResult 的data为空
三星手机的相机camera强制切换到横屏,导致Activity重启生命周期(部分机型即使配置android:configChanges也不能阻止横竖屏切换)
APP Activity A调用了系统拍照-->拍照-->在拍好照片的界面做几次横竖屏的转换后-->返回APP界面时,Activity A却被销毁了
平时开发过程中,如何做到多分辨适配的?
- 首先明确开发设备分辨率:一般选择1920*1080的分辨率(市面上主流的手机分辨率)
- 根据分辨率的不同建立不同分辨率的资源图片(可以根据切图的数量进行分析)
- 在程序启动的时候,获取当前屏幕的分辨率和密度,在代码中进行适配
- 根据目标设备,为不同分辨率的写不同的dimen文件
- 尽量使用权重分配(Google推荐)
- 根据需求可以使用代码适配以及百分比适配
- 针对特殊的设备,进行特殊的适配