android机型适配终极篇

来源:互联网 发布:云计算三层架构 编辑:程序博客网 时间:2024/05/16 15:58

一,基本概念

1.分辨率,屏幕大小,密度都代表什么。 
(1)分辨率。分辨率就是手机屏幕的像素点数,一般描述成屏幕的“宽×高”,安卓手机屏幕常见的分辨率有480×800、720×1280、1080×1920等。720×1280表示此屏幕在宽度方向有720个像素,在高度方向有1280个像素。 
(2)屏幕大小。屏幕大小是手机对角线的物理尺寸,以英寸(inch)为单位。比如某某手机为“5寸大屏手机”,就是指对角线的尺寸,5寸×2.54厘米/寸=12.7厘米。 
(3)密度(dpi,dots per inch;或PPI,pixels per inch)。从英文顾名思义,就是每英寸的像素点数,数值越高当然显示越细腻。假如我们知道一部手机的分辨率是1080×1920,屏幕大小是5英寸,你能否算出此屏幕的密度呢?哈哈,中学的勾股定理派上用场啦!通过宽1080和高1920,根据勾股定理,我们得出对角线的像素数大约是2203,那么用2203除以5就是此屏幕的密度了,计算结果是440。440dpi的屏幕已经相当细腻了。 
这里写图片描述 
2、实际密度与系统密度 
尚未发现他处使用“实际密度”和“系统密度”这两个词汇,暂时由我如此定义吧。 
“实际密度”就是我们自己算出来的密度,这个密度代表了屏幕真实的细腻程度,如上述例子中的440dpi就是实际密度,说明这块屏幕每寸有440个像素。5英寸1080×1920的屏幕密度是440,而相同分辨率的4.5英寸屏幕密度是490。如此看来,屏幕密度将会出现很多数值,呈现严重的碎片化。而密度又是安卓屏幕将界面进行缩放显示的依据,那么安卓是如何适配这么多屏幕的呢? 
其实,每部安卓手机屏幕都有一个初始的固定密度,这些数值是120、160、240、320、480,我们权且称为“系统密度”。大家发现规律没有?相隔数值之间是2倍的关系。一般情况下,240×320的屏幕是低密度120dpi,即ldpi;320×480的屏幕是中密度160dpi,即mdpi;480×800的屏幕是高密度240dpi,即hdpi;720×1280的屏幕是超高密度320dpi,即xhdpi;1080×1920的屏幕是超超高密度480dpi,即xxhdpi。 
安卓对界面元素进行缩放的比例依据正是系统密度,而不是实际密度。 
这里写图片描述 
3、一个重要的单位dp 
dp也可写为dip,即density-independent pixel。你可以想象dp更类似一个物理尺寸,比如一张宽和高均为100dp的图片在320×480和480×800的手机上“看起来”一样大。而实际上,它们的像素值并不一样。dp正是这样一个尺寸,不管这个屏幕的密度是多少,屏幕上相同dp大小的元素看起来始终差不多大。 
另外,文字尺寸使用sp,即scale-independentpixel的缩写,这样,当你在系统设置里调节字号大小时,应用中的文字也会随之变大变小。 
这里写图片描述 
4、dp与px的转换 
在安卓中,系统密度为160dpi的中密度手机屏幕为基准屏幕,即320×480的手机屏幕。在这个屏幕中,1dp=1px。 
100dp在320×480(mdpi,160dpi)中是100px。那么100dp在480×800(hdpi,240dpi)的手机上是多少px呢?我们知道100dp在两个手机上看起来差不多大,根据160与240的比例关系,我们可以知道,在480×800中,100dp实际覆盖了150px。因此,如果你为mdpi手机提供了一张100px的图片,这张图片在hdpi手机上就会拉伸至150px,但是他们都是100dp。 
dp与px的换算要以系统密度为准,720×1280的系统密度为320,320×480的系统密度为160,320/160=2,那么在720×1280中,1dp=2px。同理,在1080×1920中,1dp=3px。 
大家可以记住下面这个比例,dp与px的换算就十分easy啦! 
ldpi:mdpi:hdpi:xhdpi:xxhdpi=3:4:6:8:12,我们发现,相隔数字之间还是2倍的关系。计算的时候,以mdpi为基准。比如在720×1280(xhdpi)中,1dp等于多少px呢?mdpi是4,xhdpi是8,2倍的关系,即1dp=2px。反着计算更重要,比如你用PhotoShop在720×1280的画布中制作了界面效果图,两个元素的间距是20px,那要标注多少dp呢?2倍的关系,那就是10dp! 
这里写图片描述 
5、建议在xdhpi中作图 
安卓手机有这么多屏幕,我到底依据哪种屏幕作图呢?没有必要为不同密度的手机都提供一套素材,大部分情况下,一套就够了。 
现在手机比较高的分辨率是1080×1920,你可以选择这个尺寸作图,但是图片素材将会增大应用安装包的大小。并且尺寸越大的图片占用的内存也就越高。如果你不是设计ROM,而是做一款应用,我建议大家用PS在720×1280的画布中作图。这个尺寸兼顾了美观性、经济性和计算的简单。美观性是指,以这个尺寸做出来的应用,在720×1280中显示完美,在1080×1920中看起来也比较清晰;经济性是指,这个分辨率下导出的图片尺寸适中,内存消耗不会过高,并且图片文件大小适中,安装包也不会过大;计算的简单,就是1dp=2px啊,多好计算啊! 
做出来的图片,记着让界面工程师放进drawable-xhdpi的资源文件夹中。 
6、屏幕的宽高差异 
在720×1280中作图,要考虑向下兼容不同的屏幕。通过计算我们可以知道,320×480和480×800的屏幕宽度都是320dp,而720×1280和1080×1920的屏幕宽度都是360dp。它们之间有40dp的差距,这40dp在设计中影响还是很大的。如下图蝴蝶图片距离屏幕的左右边距在320dp宽的屏幕和360dp宽的屏幕中就不一样。 
这里写图片描述 
如果想消除这些比例差异,可以通过添加布局文件来实现。一般情况下,布局文件放在layout文件夹中,如果要单独对360dp的屏幕进行调整,你可以单做做一个布局文件放在layout-w360dp中;不过,最好是默认针对360dp的屏幕布局(较为主流),然后对320dp的屏幕单独布局,将布局文件放到layout-w320dp中;如果你想对某个特殊的分辨率进行调整,那么你可以将布局文件放在标有分辨率的文件夹中,如layout-854×480。 
7、几个资源的文件夹 
在720×1280中做了图片,要让开发人员放到drawable-xhdpi的资源文件夹中,这样才可以显示正确。个人认为仅提供一套素材就可以了,可以测试一下应用在低端手机上运行是否流畅,如果比较卡顿,可以根据需要提供部分mdpi的图片素材,因为xhdpi中的图片运行在mdpi的手机上会比较占内存。 
以应用图标为例,xhdpi中的图标大小是96px,如果要单独给mdpi提供图标,那么这个图标大小是48px,放到drawable-mdpi的资源文件夹中。各个资源文件夹中的图片尺寸同样符合ldpi:mdpi:hdpi:xhdpi:xxhdpi=3:4:6:8:12的规律。 
这里写图片描述 
如果你把一个高2px的分割线素材做成了9.png图片,你想让细线在不同密度中都是2px,而不被安卓根据密度进行缩放,怎么办?你可以把这个分割线素材放到drawable-nodpi中,这个资源文件夹中的图片,将按照实际像素大小进行显示,而不会被安卓根据密度进行缩放。即在mdpi中细线是2px(2dp),在xhdpi中细线是2px(1dp)。

8、项目实战 
这里写图片描述 
1)类似上图是美工标注后的高保真图,分辨率为640*1136,对应到安卓为720p(会有细微偏差),iOS为2@,安卓开发同学拿到图,下面的工作就比较简单了。

1.单位换算:只需要将上面的px/2,则得到代码中距离需要的dp,字体大小需要的sp。 
2.切图处理:美工的切图一律放入xhdpi文件即可 
3.适配:一般内容铺满屏幕,左右空出固定大小,这样,可以解决上述6中360dp跟320dp的屏幕的宽差异,在360dp跟320dp上看到的页面左右空出的间距会一样大,比较美观。

这里我举两个适配的例子帮助大家更好的理解。 
这里写图片描述 
上图大家觉得怎么布局比较好? 
【我加入的圈子】左边空出固定距离,右边【>】空出固定距离,中间铺满屏幕,这样可以让360dp甚至更大的手机,不至于让页面内容缩在中间一小块。再看下下面的布局:

这里写图片描述

上图又怎么布局呢?做到各种机型适配。 
我在项目中的做法是,用(屏幕的宽度(像素)-两边的间距(15dip+15dip)转成像素-中间间距(14dip+14dip))/3,这样得到每个图片的宽度,然后图片的高度设置成高图片的宽度相等(当然也可以重写view,自动设置宽等于高)

这里有人会问,为什么是(15dip+15dip),而不是(15px+15px),如果你这样问我,那我只能告诉你,从上面往下再看一遍,看下px跟dip的区别。什么?看了还不懂?因为px在不同手机上显示的具体长度是变化的,他会根据不同dpi(密度)跟手机尺寸有关,dp是物理尺寸,可以把他看成是在任何手机上,相同dp,基本看上去物理尺寸是一样的。如果不想在不同手机上,间距有的大,有的小,就这么做吧。记住一条,间距一定要是dp。 
代码如下: 
LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams)pic.getLayoutParams(); 
linearParams.width =(context.getResources().getDisplayMetrics().widthPixels-DisplayUtil.dip2px(context, 44)) / 3; //dp通过算法换算成px,这种算法会自动算出不同分辨率上dp跟sp的转换 
linearParams.height = linearParams.width; 
pic.setLayoutParams(linearParams); //使设置好的布局参数应用到控件

可能会有某些同学很不削,说做那么复杂,我用weight就搞定了哈!的确,可以用比重去做,三个图片各占比为1,再调整下边距,但是高度怎么搞,记得我上面说过,可以重写view,让这个view的高跟宽度相等,这种方式也可以。比重(weight)在适配中起到非常大的作用。

2.另类适配 
应该大家有看到有人提到过纯代码适配,就在在Java代码中动态设置每个view的宽跟高,宽跟高是通过计算得出的。比如设计图是640*1136,这个view的宽在640的设计图上是20px。所以有同学会通过DisplayMetrics metrics = res.getDisplayMetrics();screenWidth = metrics.widthPixels screenHeight = metrics.heightPixels;拿到当前屏幕的宽跟高,如果当前手机屏幕是720*1280,及screenWidth =720,screenHeight =1280,那么当前的view的宽度等于screenWidth /640*view的宽度,这样的确非常完美,每部手机都可以等比的缩放。但是代码维护跟开发难度就是成倍的增加,不建议使用。

3.不同的layout 
在res目录下创建不同的layout文件夹,比如:layout-640x360、layout-800x480……所有的layout文件在编译之后都会写入R.java里,而系统会根据屏幕的大小自己选择合适的layout进行使用。这种现在基本不会有人这么适配,不展开讨论。

0 0
原创粉丝点击