Android进阶:步骤四:Android屏幕和图片的适配

修改:https://www.jianshu.com/p/759375113de9

一、碎片化

说起来,人们口中的 Android 碎片化主要表现在 Android 品牌机型众多,Android 版本众多和 Android 设备的尺寸分辨率众多。也就是Android碎片化并不局限于手机屏幕。本文仅限于与大家一起探讨屏幕适配相关内容。

来看一张流传甚广的图片:

上图每一个方框代表一种 Android 设备的屏幕,颜色越深,这种尺寸的屏幕也就越多。也就是说,Android 开发者理论上需要适配上图中的屏幕。

然而Android屏幕碎片并没有大多数人想象的那样令人头疼。Google 早已经给了我们界面视图布局工具,你可以自定义一种或多种界面视图,以适应不同尺寸的设备。如果你还想更精益求精,那么你还可以只保留一种代码库而尽可能多的调试更多的视图。

看到上边的统计图不知大家是否有深深的同情呢?其实直到目前为止市面最为主流的仍然是几款手机屏幕分辨率:

720 x 1280

768 x 1280

800 x 1280

1080 x 1920

1440 x 2560

实际上开发者大多数情况对这些主流的设备进行适配,所以不同屏幕进行适配比想象中简单很多。不过这也仅限于 Android 手机,Android 平板并未计算在内。本文将会与大家共同讨论下屏幕相关概念以及解决方案。

荐:http://www.ifanr.com/431871

适当舍弃也是对抗 Android 碎片化重要武器

二、屏幕适配概论

屏幕适配主要解决手机屏幕和像素多样化的问题,也就是我们的App能够适应各种各样的手机屏幕。首先我们要先了解屏幕相关的概念,如果该部分相关概念不清楚将会很难理解这部分问题。

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

1)屏幕尺寸

是指屏幕对角线的长度,单位英寸1英寸 = 2.54cm

2)屏幕分辨率

是指屏幕横向和纵向像素点数,单位px1px = 1物理像素

一般以纵向像素*横向像素:1920 * 1080

3)像素密度

是指每英寸上的像素点数、单位dpi(dot per inch)的缩写、与像素无关的单位。

像素密度与屏幕尺寸、屏幕分辨率有直接的关系。

像素密度计算公式:sqrt(1920^2 + 1080^2) / 屏幕尺寸 (三角函数--勾股定理)

例:

1920^2 = 3686400

1080 ^ 2 = 1166400

3686400 + 1166400 = 48528004852800开方 = 2202.9071700822983

屏幕像素密度:2202 / 5.2 约等于424dpi 既:1英寸上有424个像素点(px)

像素密度是清晰度很重要的一个概念:即像素密度越高(dpi)代表显示屏能够以更高的密度显示图像。当然,显示的密度越高,拟真度就越高。dot per inch是图像分辨率的单位,图像dpi值越高,单位面积的像素数量就越多,所以画面的细节就越丰富。

四、什么是dp,dip,sp,pt,px及他们之间的关系

1、px

是构成图像的最小单位,也就是1px就相当于屏幕上的一个物理像素点。

2、dp、dip

是与密度无关的像素,主要是会有缩写方式不同、二者实际表示同一概念。后面统一用dp来代替。

3、dp与px的关系

Android规定:以160dp为基准,1dp = 1px。既像素密度为160dp时,此时1dp=1px,在Android中要彻底明白dp与px之间的关系才是理解适配的本质

例:

分辨率 像素密度 dp = px

480 * 320 160dp 1dp = 1px

800 * 480 240dp 1dp = 1.5px

也就是说首先要搞清楚当前设备的像素密度,才可计算像素密度与像素之间的关系。

4、dp与屏幕适配

如下图所示:(一个240px * 160px的元素)

当使用px为单位:在480*320的屏幕上显示效果,占用屏幕宽度的1/2。此时将该尺寸放在800*480屏幕上显示效果变为屏幕宽度的1/3了。

如下图所示:

当将单位改为dp时,在480*320的屏幕上显示效果:占用屏幕宽的1/2,这是因为此时1dp=1px(故:160px)。此时将该尺寸放在800*480屏幕上显示效果也是屏幕的1/2,这是因为此时1dp = 1.5px(故:240px)。

5、sp

(scaled pixels)主要用于文字大小、可以根据文字大小首选项进行缩放。效果与dp类似,在使用时要注意Google推荐以偶数为单位,如果是奇数会影响精度问题

6、pt

1pt = (1/72)英寸,既(2.54/72,单位cm)Android中并不推荐使用该单位。

在Android中为保证UI在不同屏幕类型上显示,应该始终保持:文字大小首选使用sp为单位dp作为其他元素的单位。另外也可以考虑矢量图,而不是位图。

五、什么是mdpi,hdpi,xhdpi,xxhdpi,xxxhdpi及其如何计算和区分

先来看张图,资源目录对应的像素密度范围

再来看项目工程资源目录:

通过对照,此时每个资源目录下所对应的关系是不是一目了然了呢。其实Android系统就是根据目标手机的像素密度到对应的资源目录下去查找相关资源。这就是Android屏幕适配的原理

1、mdpi

120dp ~ 160dp 此时 dp与px之间的关系:1dp = 0.75 ~ 1px

2、hdpi

160dp ~ 240dp 此时dp与px之间的关系:1dp = 1 ~ 1.5px

3、xhdpi

240dp ~ 320dp 此时dp与px之间的关系:1dp = 1.5 ~ 2px

4、xxhdpi

320dp ~ 480dp 此时dp与px之间的关系:1dp = 2 ~ 3px

5、xxxhdpi

480dp ~ 640dp 此时dp与px之间的关系:1dp = 3 ~ 4px

但是在实际开发过程中由于考虑到包大小,我们一般不会选择每个资源目录都提供(包会变得很大),比如我们只提供了一套资源:xxhdpi(320dp ~ 480dp),如果此时我们的App安装到目标为xhdpi(240dp ~ 320dp)设备上,Android系统是如何处理的呢?其实这又涉及到Android系统中加载一张资源图片最终占用的内存大小?由于不是我们本篇要讨论内容,不展开叙述,在这里直接公布答案:

系统会根据:目标的像素密度/资源所在的像素密度,得到一个值,然后根据这个值对图片资源宽高做缩放处理,以便达到最佳显示效果

荐:Drawable微技巧

六、适配不同尺寸屏幕之wrap_content、match_parent、weight

其实上边说了那么多,仅仅对屏幕适配涉及到的相关概念做一个说明,接下来才是实战解决方案:

1、支持不同的屏幕尺寸

尽量使用wrap_content、match_parent、weight(权重),避免固定尺寸值。

wrap_content与match_parent相信大家都已经用过很多了,这里只着重说明下weight。首先weight只能使用在LinearLayout中。

我们通过一个实例来说明weight的作用,如下图:

布局显示如下:

此时我们作调整:TextView1占权重3,TextView2占权重1

布局显示如下:

按照权重,我们将父布局分成4份,TextView1占3份,TextView2占1份,但实际效果却不是,这是为什么?

实际上weight属性计算规则是:推荐使用weight的时候控件设置为width设置为0dp

weight在以下3种会有不同width情况的

1、wrap_content:

首先布局会根据内容的长度而变换,不会遵守weight的比例,导致你不是你想要的效果

2、match_parent:

控件的宽度为match,当存在两个控件width为match_parent在水平的线性布局,weight分布为1,2但最终效果确是2/3:1/3

因为  计算公式:最终宽度=控件本身宽度 + (父布局宽度 - 所有组件宽度之和)* 当前控件权重/总权重

A=match_parent+(match_parent-(match_parent+match_parent))*1/3=2/3match_parent

B=match_parent+(match_parent-(match_parent+match_parent))*2/3=1/3match_parent

3、0dp:(推荐使用)

不会出现以上情况,控件的宽度永远为0dp所有,始终符合你想要的效果

weight的规则

首先按照控件自身的尺寸进行分配,然后将剩余的尺寸再按照权重进行分配。

我们的父布局宽度 = 200dp,TextView1宽度 = 50dp,TextView2宽度=50dp,两个控件共占用100dp,

然后再将剩余尺寸按照权重划分(200 - 50 - 50)/ 4 = 25

此时:

TextView1的实际宽度 = 50 + 25 * 3 = 125

TextView2的实际宽度 = 50 + 25 * 1 = 75

计算公式:

控件本身宽度 + (父布局宽度 - 所有组件宽度之和)* 当前控件权重/总权重

(当前例子:50 + (200 - 50 - 50) * 1/4 = 75)

2、RelativeLayout

这个相信大家都已经很熟悉了,主要它基于控件之间相对位置,在不同的手机屏幕上控件之间的相对位置不会发生变化。

七、适配不同尺寸屏幕之自动拉伸位图.9.PNG图片的使用

如何使用自动拉伸的位图:.9图(学名:Nine-Patch)

1、直接通过设计人员设计出.9图

这种方式就不过多叙述了。

2、通过Android Studio来完成一张普通图片到.9图

首先我们先把一张图片通过重命名修改成.9图片

在drawable文件夹中选中图片,右键create 9-Patch file

然后通过Android Studio自带编辑器预览:

其实.9图的制作就是两部分:

1、左上指定哪一部分可以被拉伸。

2、右下指定哪一部分不可以被拉伸。

上图:

左边和上边黑线区域:代表左右,和上下可以拉伸的区域

右边和下边黑线的区域:代表内容显示的区域 

没做成点9图之前:

修改之后

内容指定显示在中间,并且四角不被拉伸

当我们把鼠标放在图片上,在图片四周会有一个宽度为1px的像素点,这个像素点就是控制哪些部分是可以被拉伸,哪些是不可以被拉伸的。感兴趣可以自己去体会下,但是大部分情况下一般由设计人员直接提供(这是个精细活,需要慢慢调)。

八、适配不同尺寸屏幕之限定符处理,手机与平板适配

终于到最后了,屏幕适配之限定符

1、最小宽度限定符

 Android3.2以后,可以通过使用最小宽度限定符来为不同屏幕提供精确的布局。使用方式:如layout-sw600dp, values-sw600dp。这里的sw代表Small-Width(设备上最小的一边)的意思,当目标屏幕的最小宽度都大于480dp时,屏幕就会自动到带sw480dp后缀的资源文件里去寻找相关资源文件,这里的最小宽度是指屏幕宽高的较小值,每个屏幕都是固定的,不会随着屏幕横向纵向改变而改变。

如下图分别提供160dp~ 820dp的values资源:

如下图分别提供7英寸平板与10英寸平板的layout资源:

如果是电视机要写到更大的值:如layout-sw1000dp,layout-sw2000dp

Android3.2之前?

使用尺寸限定符layout-large/???,values-large/???由于目前3.2之前的设备微乎其微,故不再展开叙述。

2、屏幕方向限定符

实际开发过程中这种需求较少。

values-sw600dp-land(最小宽度600dp横向)、values-sw600dp-port(最小宽度600dp纵向)

3、布局别名

如果我们仅建立一个layout资源目录,此时可以通过在values目录下定义layout.xml文件,如下图:

此时注意name要相同如下图:

系统会自动根据Small-Width到指定目录下查找,此时他们对应的布局文件并不相同,从而达到布局动态选择。

九、总结

1、适配不同尺寸避免写死的尺寸值;wrap_content,match_parent,weight。

2、使用相对位置的RelativeLayout。

3、考虑使用自动拉伸.9图

4、限定符;最小宽度限定符,屏幕方向限定符,布局别名。

相信如果你能够熟练运用这些进行界面搭建,就如同文章开头说到,屏幕适配并没有想想中的那么困难。

猜你喜欢

转载自blog.csdn.net/qq_17846019/article/details/83994656
今日推荐