DP是一种绝对的物理的尺寸定义,DP的作用是让同一数值在不同的分辨率下展示出大致相同的物理尺寸
Density: 转换比例.DP和PX之间的比例.在dpi 160时Density =1,也就是Density=Dpi/160;
那么1dp到底有多少呢??在标准屏幕密度下,1英寸有160px,这时1px=1dp,也就是说1英寸有160dp.那么1dp=1/160英寸.1dp=2.54厘米/160=0.15875毫米.
在android中无论什么样密度的屏幕,100dp永远全显示出近似15.875毫米的长度.因此造成的问题就是在不同屏幕尺寸下,同样DP的组件所占据的屏幕比例是不同的.
在java代码里使用的单位全是px,而xml中使用的都为dp
| ldpi | mdpi | hdpi | xhdpi | xxhdpi |
DPI | 120 | 160 | 240 | 320 | 480 |
分辨率 | 240*320 | 320*480 | 480*800 | 720*1280 | 1920*1080 |
Density | 0.75 | 1 | 1.5 | 2 | 3 |
系统分根据这五种级别进行适配
3 适配用的文件夹后缀.根据优先极分为
smallestWidth(sw<N>dp)>可用宽度(w<N>dp)>可用高度(h<N>dp)>屏幕尺寸(normal)>屏幕像素密度 (hdpi)>分辨率(1280*720)
a smallesWidth 最小尺寸:如sw480dp,这是个坑宽爹的属性.最小是不管宽或高的.所以基本没用.b 可用宽度:如as创建项目时自带的w820dp.系统会匹配与屏幕宽度最接近并小与等与屏幕宽度的文件夹.c 可用高度:如h820dp 同可用宽度对与这两种后缀.屏幕在横竖屏切换时会读不同的配置.d 屏幕尺寸:这是API 4以后出来的新属性,括号内为此级别的屏幕最小尺寸要求.有small(320x426 dp ),normal( 320x470 dp),large(480x640 dp),另外API 9增加了xlarge(720x960 dp).e 屏幕像素密度(DPI),这个就不用说了见上表.xhdpi要求API 8,xxhdpi要求API 16,API 18新增xxxhdpi(640dpi).f 分辨率.这个后缀并不存在与官方文档中.但实际上是存在的.写法为-1280x720 数值大的放在前面.(这个看起来很好.但实际上匹配起来也有坑,后面会说到).
1 系统会根据读取的资源文件夹的Density和屏幕Density的比例进行缩放.比如屏幕320dpi,如果是从默认文件夹里读取一个30px*30px的图片.实际上会放大成 60*60的图片读取到内存中.2 如果系统找不到最匹配的配置时会使用默认的配置.但不总是会读取默认配置.实际上系统在读取drawable时的匹配是以缩放的效率来决定的.比如匹配ldpi,系统会优先选择hdpi而不是mdpi.因为缩小一半比缩小3/4要效率同理,在匹配xxhdpi时系统会优先选择mdpi(默认)而不是xhdpi(这是个人根据上面的例子进行的推论,在缩放时系统倾向与缩小还是放大这点还不明确)
1 hdpi 匹配:通过屏幕自身的Dpi和分辨率来查找相应的后缀为?hdpi的资源文件夹.如果Dpi不能完全对应,则看分辨率.
最明显的例子是华为的Mate8 367的Dpi更接近xhdpi,但因为分辨率1080P完全匹配xxhdpi.所以从xxhdpi中读取资源
dpi的匹配顺序是先查找完全匹配的文件夹,如果没有,则向大一级的dpi匹配;如果没有比自身大的dpi,则会向小一级的dpi匹配。最后才匹配values文件夹
原来的认识是没有匹配会像小一级的dpi匹配,结果http://2kpurple.github.io/2014/08/14/Android-values-folder/这篇文章证明了事践才是检验真理的最高标准.2 分辨率匹配:这个也有个坑.屏幕适配是按app的屏幕尺寸来适配的.注意是app的屏幕尺寸.当初android在决定这个适配策略时没有想到几年后他们会搞出一个叫虚拟按键的东东..所以分辨率匹配在有虚拟按键的手机上会有坑.例如Galaxy Nexus(1280x720 ),却可以匹配到values-hdpi-1024x600
3 屏幕尺寸匹配:以前从来都不知道还有这个东东.优先度还比dpi高.然而卵并卵.large这个东西兼容性太强.在当今天主流的各种手机面前,毛用都没有.
四 主流屏幕的相关参数
屏幕尺寸(英寸) | 分辨率 | DPI | Density(转换率 ) | 宽度DP | 高度DP | 读取资源 |
6.0 | 1080p | 367 | 2.5 | 432 | 768 | xxhdpi |
5.5 | 1080p | 400 | 3 | 360 | 640 | xxhdpi |
5.2 | 1080p | 423 | 3 | 360 | 640 | xxhdpi |
5.0 | 1080p | 440 | 3 | 360 | 640 | xxhdpi |
4.7 | 720p | 312 | 2 | 360 | 640 | xhdpi |
非主流 三星S7.
5.1 | 2k(2560x1440) | 576 | 3.5(计算值) | 441 | 731 | xxxhdpi(推测 ) |
都说安卓碎片化严重.但表格出来后,发现还是很合谐的.360dp*640dp占据了主流.xxhdpi可以说占领了大半江山.可以说现在是屏幕适配最好的时候.
从这个表可以看到,从5.0-5.5.都是360Dp的宽度.证明以上每一种屏上的1Dp长度并不是完全相同,而是近似相同.
当然.坑爹的不是没有.
Mate8是个很神奇的机型.367的dpi.2.5的density是个很坑爹的存在.没有任何drawable文件夹能完全匹配.读取一个1080p的图片时会缩小成1600*900加载到内存中.如果想不缩放,只能用nodpi.但nodpi的匹配优先级是最低的.试过-sw430dp-nodpi,依然不起作用.
现在主流的5-5.5/1080P也是个很奇怪的配置.400的dpi无论怎么算density都应该是2.5而不是3...
非主流的S7的出现标志着2k屏甚至4k屏开始出现在手机上了.xxxhdpi以后肯定会有一席之地.xhdpi会慢慢退出手机界.
五 总结
1 drawable 应用中完全有可以只用两套,甚至一套图.xxhdpi是必不可少的.xhpi可以考虑让系统去缩小xhdpi的图.至与要不要为S7去配个xxxhdpi,考虑到中国棒子粉特别多,还是搞一套吧.其它的就可以不用放了.drawable里可以只放shape2 values 准确来说应该是dimens.这个比drawable麻烦些.大多是准备几套dimens.设定一套为基础比如padding=16dp,另一套根据Density进行缩放,如padding=24dp.这种做法从本质上来讲是为了尽量保证比例.
但还是有问题.
一 难免会遇到个别机型会乱读dimens.
二 有时候同比缩放并不招人喜欢.比如字体大小.
三 坑爹的虚拟按键,把屏幕从16:9变成了差不多4:3.有时同样的布局放上去有种范冰冰变凤姐的感觉.
3 知道了基础和原理,屏幕适配其实也很容易.最大放小,匹配大多数. 最好的适配方式就是把UI妹子拉到自己身边,一边聊天,一边微调.最后屏幕适配好了.妹子也不远了.
最后附上官方说明文档.翻译得一般.比机翻强半分钱.仅作参考
At runtime, the system ensures the best possible display on the current screen with the following procedure for any given resource:
运行时,系统确保尽可能的按照下流程获取给定的资源显示当前屏幕上.
- The system uses the appropriate alternative resource
Based on the size and density of the current screen, the system uses any size- and density-specific resource provided in your application. For example, if the device has a high-density screen and the application requests a drawable resource, the system looks for a drawable resource directory that best matches the device configuration. Depending on the other alternative resources available, a resource directory with the
hdpi
qualifier (such asdrawable-hdpi/
) might be the best match, so the system uses the drawable resource from this directory.系统使用适当的替代资源
基于当面屏幕的尺寸和密度,系统使用由你的应用提供的任何尺寸和密度特性的资源.例如,如果设备是高密度的屏幕而应用需要drawable资源,系统会去寻找与设置配置最匹配的drawable资源文件夹.
在可获得的资源中,一个hdpi级别(例如drawable-hdpi/)的文件夹可能是最匹配的.这样系统就会使用这个文件夹里的资源.
- If no matching resource is available, the system uses the default resource and scales it up or down as needed to match the current screen size and density
The "default" resources are those that are not tagged with a configuration qualifier. For example, the resources in
drawable/
are the default drawable resources. The system assumes that default resources are designed for the baseline screen size and density, which is a normal screen size and a medium density. As such, the system scales default density resources up for high-density screens and down for low-density screens, as appropriate.However, when the system is looking for a density-specific resource and does not find it in the density-specific directory, it won't always use the default resources. The system may instead use one of the other density-specific resources in order to provide better results when scaling. For example, when looking for a low-density resource and it is not available, the system prefers to scale-down the high-density version of the resource, because the system can easily scale a high-density resource down to low-density by a factor of 0.5, with fewer artifacts, compared to scaling a medium-density resource by a factor of 0.75.
如果没有可获得的匹配资源.系统会使用默认的资源并且根据当前的屏幕尺寸和密度进行缩放.这个默认的资源是没有标记配置的.例如drawable/文件夹就是个默认的drawable资源.系统把默认的资源设计成基础的屏幕尺寸和密度.使用的是noraml尺寸和medium密度.省略了后缀显示.系统会以默认的密度去根据目标屏幕的密度去进行缩放处理.然而.当系统去寻找一个指定密度尺寸的资源时没有找到对应的资源文件夹,不会总是使用默认的资源. 当缩放时系统可能使用另一个特定密度的资源,以提供更好的结果.例如.当寻找一个low密度(ldpi 120dpi)的资源但没有找到.系统更愿意去缩小一个high密度的资源.相比把一个midium密度(mdpi 160dpi)的资源缩小到0.75,系统把一个high密度(hdpi 240dpi)缩小到0.5会更容易.
参考文章:http://developer.android.com/intl/zh-cn/guide/practices/screens_support.html
http://developer.android.com/intl/zh-cn/guide/topics/resources/providing-resources.html
http://2kpurple.github.io/2014/08/14/Android-values-folder/
http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=498&extra=page%3D1(这个文章很值得一读)