Android适配是一个大坑,你可能早有耳闻。适配问题到底有多坑?为什么坑?以及如何从坑里爬出来?
概述
Android屏幕尺寸各异,而我们不可能根据各种尺寸都设计一套原型图去匹配,我们需要利用适配这一个过程把同一张原型图设计的样式尽可能以同样地视觉效果呈现在不同地屏幕上。
Android适配最核心的问题有两个,其一,就是适配的效率,即把设计图转化为App界面的过程是否高效,其二如何保证实现UI界面在不同尺寸和分辨率的手机中UI的一致性。
参数解析
1、像素(px)和分辨率。
我们的显示屏是由一个一个肉眼看不见但是放大镜可以看见的小点点组成的,这些点点就是像素,是物理世界中存在的东西。分辨率是你的显示屏一共有多少像素。我们平时说的分辨率是1920*1080,就是所谓的1080p,意思是显示器上水平方向有1920个像素,垂直方向有1080个像素,乘起来大概是200W个像素。
2、屏幕密度(dpi)。
屏幕密度是对角线上每英寸的屏幕包含多少个像素。比如你手里的iPhone 6 plus,对角线有5.5英寸长,分辨率是1920*1080,那么根据勾股定理(还记得吗,小学语文老师讲过的哦),对角线上有2203个像素,屏幕密度就是2203/5.5=400,单位是dpi或者ppi,二者是一个意思。
在此基础上,Google顺便把手机按照屏幕的密度分了几个档次:
现在主流的手机,都可以找到自己所在的屏幕密度档次。比如一般来说720p的手机是xhdpi,1080p的是xxhdpi。还有一种情况,比如同样都是4英寸的480800和4英寸的960540,尽管实际算出来的dpi不一样,但是都要归到hdpi这一档,dpi都变成了240,这是Android系统做的一种近似处理,目的是为了简化计算。也就是说,虽然实际上手机的密度有很多种,但是大家会找到自己的近似区间,然后用区间的代表值去做运算。
3、密度无关像素(dp)
dp是一个虚拟的概念,是在程序运行的时候算出来的。怎么理解呢?Android设备那么多,分辨率也那么多,直接学iOS用px做单位肯定不行的。为此Google搞了一个叫dp的东西,换算公式是dp=(dpi/160)*px。也就是说,在密度为160dpi的屏幕上,1px就是1dp。依次类推,在320dpi的屏幕上,1dp就是2px。屏幕密度越大,1个dp对应的px也就越多。
根据前面讲的屏幕密度区间,你可以记住这样一个简单的计算方法:
- mdpi区间的手机,dp=px。
- hdpi区间的手机,dp算px要乘以1.5。
- xhdpi区间的手机,dp算px要乘以2。
- xxhdpi区间的手机,dp算px要乘以3。
- xxxhdpi区间的手机,dp算px要乘以4。
dp理解
假设我们现在有两台手机,一台是1280720,320dpi,一台是19201080,480dpi。设计师同学给了一个标注是360px,放在第一台手机上正好是屏幕宽度的一半,但是放在第二台的手机上,则只有宽度的1/3了。这显然是不行的。现在设计师改成了180dp,那么根据公式,在320dpi的手机上,180dp=360px是屏幕宽度720px的一半。在480dpi的手机上,180dp=540px也是屏幕宽度1080px的一半。所以你看到了,dp是用来屏蔽手机的像素密度的差异的,相同dp的标注,在不同分辨率的屏幕上,实际大小都是一致的(从这个角度讲,你可以把dp看做是一个类似厘米、英寸这样的绝对的长度单位,大约160dp等于1英寸)。
4.Android屏幕适配常见方法
4.1 适配常见方法
尺寸适配dimen适配布局适配代码适配图片适配
4.2 尺寸适配
4.2.1 布局文件设置宽高宽高设置参数:
有的时候用dp,有的时候用px,大多数用dpdp:dp(dip):px = dp * 密度比,与屏幕像素有对应关系,设置成dp后,在不同分辨率的手机上有可能尺寸会不一样 px:像素,比如小分辨率手机上一像素和大分辨率手机上一像素,所显示的图像是不一样的 理解dp和px之间对应的关系,不同分辨率的手机用不同的dp值来适配4.2.2 密度比密度比是固定的,可以查询文档Develop—>API Guides—>Best Practices—>Supporting Multiple mdpi手机:160dpi 是基准线,1px = 1dp * 1,其他手机的密度比 = 自己的dpi/160代码获取密度比:getResources().getDisplayMetrics().densityldip:120px = 160dp * 0.75mdpi:160px = 160dp * 1hdpi:240px = 160dp * 1.5xhdpi:360px = 180dp * 24.2.3 dimen适配1.在默认的values中的dimens文件下声明(类似于Strings.xml) 16dp 16dp 160dp<?xml version="1.0" encoding="utf-8"?> 120dip 220dip <?xml version="1.0" encoding="utf-8"?> 80dip 2.在布局文件中引用3.新建需要适配的values-XXX(比如values-1280x720,注意规范大值在前)4.在新建values-1280x720中的dimens.xml文件中 * 180dp5.所有手机适配找对应的默认的dimens * 思考:如何计算dpi?如何计算手机密度比?能够用dp适配所有手机吗? * dp不能适配所有手机; * 举个例子:按钮占屏幕宽度一半,把宽度设置成160dp,120px和160px和240px可以占屏幕一半,但是360px则小于屏幕一半; * 如果把宽度设置成180dp,那么360dp可以占屏幕一半,但其他几个又不行。 * 如果要适配所有手机的控件宽度为屏幕宽度的一半,该怎么做呢?用dimen
4.2 代码适配
4.3 布局适配
有可能在不同的手机布局中,控件排列的位置不一样
1.位置不一样不同的手机在运行的时候选择不同的布局(布局名称一样,类似于dimens),比如:2.控件不一样不能用布局适配了;为什么?布局能够实现界面效果,但是完成布局后在代码中,由于控件都不一样,所以会找这两套布局的id,还要做判断,根据不同的布局做两套代码(如果页面复杂,给控件设置参数等十分繁琐)3.适用场景不同的手机的控件的位置不一样,发生了位置变化才会用到布局适配,实际开发中用的很少
4.4 权重适配
4.5 图片适配
1.图片的查找顺序注意:一般手机 ldpi<drawable<mdpi<hdpi<xhdpi<xxhdpi 先找自己对应的文件夹,再找大分辨率,再找小分辨率注意:mdpi手机 ldpi<mdpi<drawable<hdpi<xhdpi<xxhdpi 先找自己对应的文件夹,找drawable文件夹,再找大分辨率,再找小分辨率适配主流手机,1920 * 1080 1080 * 720 800 * 480,高清图、背景图(全屏展示)准备多套 。小图片 准备一套高分辨率的;比如按钮,图标等为了是apk瘦身,有些图片不要准备多套,Android分辨率种类太多了;即使适配主流手机,展示比较清楚的背景图(比如:欢迎界面),可以准备多套2.在小分辨率展示高清图,放到大分辨率会出现什么情况呢?比如:你针对800480分辨率手机做了背景图图片,正好完全展示;如果把它放到大分辨率1280720上,会对图片进行拉伸,会使像素点变大,可能会看到锯齿或者模糊的东西。
以上就是Android开发中的适配解析,许多疑难杂症都可以从中解决。或许还有一些Android适配的其他技术,可以点击《Android核心技术手册》里面包含Android中大部分核心技术。该文档里面分为30多个知识点整理;需要可以参考学习一下。
Android
- 通配符适配困境
- 传统dp适配困境
一般我们设计图都是以固定的尺寸来设计的。比如以分辨率750px * 1334px来设计,以density为3来标注,也就是屏幕其实是350dp * 667dp。如果想在所有设备上显示完全一致,其实是不现实的,因为屏幕高宽比不是固定的,各种宽高比层出不穷,宽高比不同,显示完全一致就不可能了。但是通常下,我们只需要以宽或高一个维度去适配,比如我们Feed是上下滑动的,只需要保证在所有设备中宽的维度上显示一致即可,再比如一个不支持上下滑动的页面,那么需要保证在高这个维度上都显示一致,尤其不能存在某些设备上显示不全的情况。同时考虑到现在基本都是以dp为单位去做的适配,如果新的方案不支持dp,那么迁移成本也非常高。因此,总结下大致需求如下:支持以宽或者高一个维度去适配,保持该维度上和设计图一致;注意是某一个维度支持dp和sp单位,控制迁移成本到最小。