Android机型适配终极篇

关注微信公众号:程序员小安,精彩文章按期推送。java

一、分辨率,屏幕大小,密度

(1)分辨率。分辨率就是手机屏幕的像素点数,通常描述成屏幕的“宽×高”,安卓手机屏幕常见的分辨率有480×800、720×1280、1080×1920、1440x2560的2K屏等。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的屏幕已经至关细腻了。android

这里写图片描述

二、实际密度与系统密度

“实际密度”就是咱们本身算出来的密度,这个密度表明了屏幕真实的细腻程度,如上述例子中的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。 安卓对界面元素进行缩放的比例依据正是系统密度,而不是实际密度。 将必定范围的屏幕密度的设备视为一个特定的密度,好比屏幕密度在240左右的设备视为高密度(hdpi),在320左右的视为超高密度(xhdpi)等。ios

这里写图片描述

三、dp、sp、px的区别

px:即像素,1px表明屏幕上一个物理的像素点;px单位不被建议使用,由于一样100px的图片,在不一样手机上显示的实际大小可能不一样,偶尔用到px的状况,是须要画1像素表格线或阴影线的时候,用其余单位如dp会显得模糊。 dp也可写为dip,即density-independent pixel。你能够想象dp更相似一个物理尺寸,好比一张宽和高均为100dp的图片在320×480和480×800的手机上“看起来”同样大。而实际上,它们的像素值并不同。dp正是这样一个尺寸,无论这个屏幕的密度是多少,屏幕上相同dp大小的元素看起来始终差很少大。 sp:sp和dp很相似但惟一的区别是,Android系统容许用户自定义文字尺寸大小(小、正常、大、超大等等),因此目前主流应用字体大小已经改用dp,不用sp,省去用户手动调整字体适配的麻烦。程序员

这里写图片描述

四、dp与px的转换

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。 中密度和高密度的缩放比例,720×1280的系统密度为320,320×480的系统密度为160,320/160=2,那么在720×1280中,1dp=2px。同理,在1080×1920中,1dp=3px。 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! 实际程序中根据不一样机型,能够用代码计算相应的转换。 当安卓系统字号设为“普通”时,sp与px的尺寸换算和dp与px是同样的。好比某个文字大小在720×1280的PS画布中是24px,那么告诉工程师,这个文字大小是12sp。 这里写图片描述微信

五、建议在xdhpi中做图

安卓手机有这么多屏幕,我到底依据哪一种屏幕做图呢?没有必要为不一样密度的手机都提供一套素材,大部分状况下,一套就够了。 如今手机比较高的分辨率是1080×1920,你能够选择这个尺寸做图,可是图片素材将会增大应用安装包的大小。而且尺寸越大的图片占用的内存也就越高。若是你不是设计ROM,而是作一款应用,我建议你们用PS在720×1280的画布中做图。这个尺寸兼顾了美观性、经济性和计算的简单。美观性是指,以这个尺寸作出来的应用,在720×1280中显示完美,在1080×1920中看起来也比较清晰;经济性是指,这个分辨率下导出的图片尺寸适中,内存消耗不会太高,而且图片文件大小适中,安装包也不会过大;计算的简单,就是1dp=2px啊,多好计算啊! 作出来的图片,记着让界面工程师放进drawable-xhdpi的资源文件夹中。 xhdpi (320dpi, 2x) 同iOS @2x 750x1334 xxdpi (480dpi, 3x) 同iOS @3x 1242x2208(除以1.15,则等比缩放到android的1080*1920) 淘宝选择2x标注,3x切图,具体讲解以下:blog.csdn.net/zx_android/…markdown

六、屏幕的宽高差别

在720×1280中做图,要考虑向下兼容不一样的屏幕。经过计算咱们能够知道,320×480和480×800的屏幕宽度都是320dp,而720×1280和1080×1920的屏幕宽度都是360dp。它们之间有40dp的差距,这40dp在设计中影响仍是很大的。以下图蝴蝶图片距离屏幕的左右边距在320dp宽的屏幕和360dp宽的屏幕中就不同。ide

这里写图片描述

若是想消除这些比例差别,能够经过添加布局文件来实现。通常状况下,布局文件放在layout文件夹中,若是要单独对360dp的屏幕进行调整,你能够单作作一个布局文件放在layout-w360dp中;不过,最好是默认针对360dp的屏幕布局(较为主流),而后对320dp的屏幕单独布局,将布局文件放到layout-w320dp中;若是你想对某个特殊的分辨率进行调整,那么你能够将布局文件放在标有分辨率的文件夹中,如layout-854×480。oop

七、几个资源的文件夹

在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.资源加载优先级

Google官方文档显示以下: 若是有最匹配的资源(e.g. 设备是HDPI,存在hdpi的资源),则删除其余的资源 若是没有最佳匹配资源,优先匹配更高dpi的资源,缩小合适的比例之后使用(e.g. 设备是HDPI,未能找到hdpi的资源,可是有xhdpi的资源,则把XHDPI的资源缩小的3/4之后使用),并排除其余的资源(Google解释说,由于执行缩小操做比执行放大操做更加方便,因此高dpi资源优先与低dpi资源,不过,我的认为对于大部分图片来讲,大图缩小形成的失真应该是小于小图放大形成的失真) 若是没最佳匹配的资源,也不存在更高dpi的资源,则使用dpi更低的资源,并放大合适的比例之后使用(e.g. 设备为HDPI,未能找到hdpi以及更高的资源,单存在mdpi的资源,则把mdpi的资源放大到3/2之后使用),并删排除其余资源

原则上来讲,dalvik优先使用符合设备dpi的资源,其次是dpi较低的高dpi资源,再次是dpi较高的高dpi资源,最后采用nodpi的资源,由此,根据设备自身的dpi的不一样,不一样dpi资源的优先级是有差别的(忽略mdpi&hdpi):

设备dpi 优先级顺序(由高到低) tvdpi tvdpi>hdpi>xhdpi>xxhdpi>mdpi>default>ldpi>nodpi hdpi hdpi>xhdpi>xxhdpi>tvdpi>mdpi>default>ldpi>nodpi xhdpi xhdpi>xxhdpi>hdpi>tvdpi>mdpi>default>ldpi>nodpi xxhdpi xxhdpi>xhdpi>hdpi>tvdpi>mdpi>default>ldpi>nodpi 另外,除了nodpi之外,使用其余dpi资源前,还须要根据缩放比进行缩小/放大操做。

九、项目实战

这里写图片描述

1)相似上图是美工标注后的高保真图,分辨率为640*1136,对应到安卓为720p(会有细微误差),ios为2@,安卓开发同窗拿到图,下面的工做就比较简单了。

1.单位换算:只须要将上面的px/2,则获得代码中距离须要的dp,字体大小须要的sp。 2.切图处理:美工的切图一概放入xhdpi文件便可

这里我举两个适配的例子帮助你们更好的理解。

这里写图片描述

1.上图你们以为怎么布局比较好?【代码适配】 解答:【我加入的圈子】左边空出固定距离,右边【>】空出固定距离,中间铺满屏幕,这样可让360dp甚至更大的手机,不至于让页面内容缩在中间一小块。再看下下面的布局:


这里写图片描述

2.上图又怎么布局呢?作到各类机型适配。【动态布局适配】 我在项目中的作法是,用(屏幕的宽度(像素)-两边的间距-中间间距)/3,这样获得每一个图片的宽度,而后图片的高度设置成高图片的宽度相等(固然也能够重写view,自动设置宽等于高) 代码以下: LinearLayout.LayoutParams linearParams = (LinearLayout.LayoutParams)pic.getLayoutParams(); linearParams.width =(context.getResources().getDisplayMetrics().widthPixels-DisplayUtil.dip2px(context, 44)) / 3; linearParams.height = linearParams.width; pic.setLayoutParams(linearParams); //使设置好的布局参数应用到控件

3.weight也能够搞定了!的确,能够用比重去作,三个图片各占比为1,再调整下边距,可是高度怎么办,前面说过上,能够重写view,让这个view的高跟宽度相等,这种方式也能够。【比重适配

4.【另类适配】 应该你们有看到有人提到过纯代码适配,就在在java代码中动态设置每一个view的宽跟高,宽跟高是经过计算得出的。好比设计图是6401136,这个view的宽在640的设计图上是20px。因此有同窗会经过DisplayMetrics metrics = res.getDisplayMetrics();screenWidth = metrics.widthPixels screenHeight = metrics.heightPixels;拿到当前屏幕的宽跟高,若是当前手机屏幕是7201280,及screenWidth =720,screenHeight =1280,那么当前的view的宽度等于screenWidth /640*view的宽度,这样的确很是完美,每部手机均可以等比的缩放。可是代码维护跟开发难度就是成倍的增长,不建议使用。

5.【不一样的layout适配】 在res目录下建立不一样的layout文件夹,好比:layout-640x360、layout-800x480……全部的layout文件在编译以后都会写入R.java里,而系统会根据屏幕的大小本身选择合适的layout进行使用。这种如今基本不会有人这么适配,不展开讨论。

6.dimen尺寸资源文件的使用 dimen.xml在values文件夹下面

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="btn_width">16dp</dimen>
    <dimen name="btn_height">16dp</dimen>
</resources>
复制代码

布局中的使用:

<Button   
android:text="@string/test_dimen1"   
android:id="@+id/Button01"   
android:layout_width="@dimen/btn_width"   
android:layout_height="@dimen/btn_height"/>
复制代码

文件夹含义: values-v11 -------API 11+表明android 3.0 +,意思是在API11设备上,该目录下的dimens.xml代替res/values/dimens.xml values-480x320、values-800x480等 ------------意思是在不一样分辨率下,该目录下的dimens.xml代替res/values/dimens.xml 反编译某主流电商APP后的截图以下所示: 反编译某主流电商APP后的截图

ppt讲解下载地址:关注微信公众号:程序员小安,公众号留言便可获取


若有错误欢迎指出来,一块儿学习。 在这里插入图片描述

相关文章
相关标签/搜索