那些值得你去细细研究的Drawable适配

本文详细探讨了Android中Drawable的适配问题,包括Android适配基础知识,如长度单位(dp、dip、dpi、sp、px)、屏幕尺寸、分辨率和密度的关系。还介绍了占用内存测试,解释了同一图片在不同drawable目录下的内存占用差异。最后,讨论了只做一套配图时应放在drawable-xxdpi文件夹的原因,并解释了图片在硬盘和内存中的大小区别。
摘要由CSDN通过智能技术生成

转载请注明:http://blog.csdn.net/wrg_20100512/article/details/51295317
一直都是在自家的盒子上开发App,很少接触到Android适配的问题。但是不得不说Android严重的碎片化,对于应用开发者来说,学会Android适配的是必要的。意识到自己就得不足就马上行动,而Android适配的问题太多,有屏幕尺寸的适配、屏幕分辨率的适配以及android不同系统版本的适配。反映在代码上来说,就是需要在资源文件上面下功夫,主要是layout和drawable文件目录下的文件,这里主要就研究一下drawable的适配。

Q:Android项目中那么多drawable(mdpi、hdpi、xhdpi、xxhdpi等),那应用的配图应该放在哪个目录之下呢?
这个问题先不解答,先了解一下Android适配的基本知识。

Android适配的基本知识

Android中的长度单位

Android中与适配有关的主要的长度单位有dp、dip、dpi、sp、px。下面一一解释一下。

  • px(pixel)

表示屏幕实际的像素。例如,1200×1920的屏幕在横向有1200个像素,在纵向有1920个像素。

  • dpi(dot per inch)

表示屏幕密度是指每英寸上的像素点数。Android将根据不同的dpi将Android设备分成多个显示级别。具体如下:

这里写图片描述

正如drawable目录和mipmap目录有ldpi、mdpi、hdpi、xhdpi、xxhdpi之分。

这里解释一下mipmap和drawable的区别
在Android studio开发中,新建一个module的时候不同与Eclipse(会生成drawable、drawable-ldpi、drawable-mdpi、drawable-hxpi等等),在资源文件中会生成mipmap-hdpi、mipmap-mdpi、mipmap-xhdpi、mipmap-xxhdpi和一个drawable目录。
Q:这个一系列的mipmap文件夹是用来干啥的呢?
A:打开所有以mipmap开头的文件夹发现里面的文件都是ic_launcher.png。
Q:ic_launcher.png以前都是在以drawable开头的目录中,现在将ic_launcher.png放在以mipmap开头的文件夹,是不是以后的开发不需要以drawable开头的目录了。
A:对于这个问题谷歌官方有说法
drawable/
For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe Drawable shapes or Drawable objects that contain multiple states (normal, pressed, or focused).
意思是说以drawable开头的目录存放的文件有png、jpeg、gif格式图片文件、.9图片以及一些XML文件。
mipmap/
For app launcher icons.
而以mipmap开头的目录存放的是App的图标。

  • dp

也叫dip(density independent pixel)直译为密度无关的像素。我们猜测如果使用了这个单位,我们在不同屏幕密度的设备上显示的长度就会是相同的。问题来了,在屏幕上显示图像时都是在屏幕上填充像素点,而使用这种与密度无关的像素(我们在布局文件中使用的 dp/dip 就是与密度无关的像素)是如何转换成像素的呢?
其实在安卓中,将屏幕密度为160dpi的中密度设备屏幕作为基准屏幕,在这个屏幕中,1dp=1px。其他屏幕密度的设备按照比例换算,具体如下表:

这里写图片描述

由上表不难计算1dp在hdpi设备下等于1.5px,同样的在xxhdpi设备下1dp=3px。这里我们从dp到px解释了Android中不同屏幕密度之间的像素比例关系。
下面换一个角度,从px到dp的变化来说明这种比例关系。
就拿为App设计icon来说,为了让App的icon在不同的屏幕密度设备显示相同(这里我们选择在以mipmap开头的目录中都要设计一个icon),就必须要icon在屏幕中占据相同的dp。那么对于不同的屏幕密度(MDPI、HDPI、XHDPI、XXHDPI 和 XXXHDPI)应按照 2:3:4:6:8 的比例进行缩放。比如说一个icon的尺寸为48x48dp,这表示在 MDPI 的屏幕上其实际尺寸应为 48x48px,在 HDPI 的屏幕上其实际大小是 MDPI 的 1.5 倍 (72x72 px),在 XDPI 的屏幕上其实际大小是 MDPI 的 2 倍 (96x96 px),依此类推。

备注:
图片的描述有两种:
1、仅仅通过宽高的像素。
2、通过图片分辨率(不同于屏幕分辨率,单位英寸中所包含的像素点数)和尺寸大小。

  • sp

sp,即scale-independent pixels,与dp类似,但是可以在设置里面调节字号的时候,文字会随之改变。当安卓系统字号设为“普通”时,sp与px的尺寸换算和dp与px是一样的。

屏幕尺寸、屏幕分辨率、屏幕密度

  • 屏幕尺寸

设备的物理屏幕尺寸,指屏幕的对角线的长度,单位是英寸,1 inch = 2.54 cm。比如某某手机为“5寸大屏手机”,就是指对角线的尺寸,5寸×2.54厘米/寸=12.7厘米。

  • 屏幕分辨率

也叫显示分辨率,是屏幕图像的精密度,是指屏幕或者显示器所能显示的像素点有多少。一般以横向像素×纵向像素表示分辨率,如1200×1920表示此屏幕在宽度方向有1200个像素,在高度方向有1920个像素。

  • 屏幕密度

屏幕密度是指每英寸上的像素点数,单位是dpi(dot per inch)或者ppi(pixels per inch)。顾名思义,就是每英寸的像素点数,数值越高当然显示越细腻。屏幕密度与屏幕尺寸和屏幕分辨率有关。例如在屏幕尺寸一定的条件下,屏幕分辨率越高屏幕密度越大,反之越小。同理在屏幕分辨率一定的条件下,屏幕尺寸越小屏幕密度越大,反之越小。

屏幕密度的计算
不同于屏幕尺寸和屏幕分辨率,这两个值是可以直接得到的。屏幕密度需要我们计算得到。例如我的手机的分辨率是1200×1920,屏幕尺寸是5寸的。根据屏幕尺寸、屏幕分辨率和屏幕密度定义不难看出他们之间的关系如下图:

这里写图片描述

这样根据勾股定理,我们得出对角线的像素数大约是2264,那么用2264除以7就是此屏幕的密度了,计算结果是323。
备注:
在Android中,上面的出现的0.75,1,1.5,2,3,4才是屏幕密度(density)。而120,160,240,320,480,640是屏幕密度dpi(densityDpi)。

  • 实际密度与系统密度

实际密度就是我们自己算出来的密度,这个密度代表了屏幕真实的细腻程度,如上述例子中的323dpi就是实际密度,说明这块屏幕每寸有323个像素。
7英寸1200×1920的屏幕密度是323,5英寸1200×1920的屏幕密度是452,而相同分辨率的4.5英寸屏幕密度是503。如此看来,屏幕密度将会出现很多数值,呈现严重的碎片化。而密度又是安卓屏幕将界面进行缩放显示的依据,那么安卓是如何适配这么多屏幕的呢?
其实,每部安卓手机屏幕都有一个初始的固定密度,这些数值是120、160、240、320、480,这些就是android为不同设备设定的系统密度。
得到实际密度以后,一般会选择一个最近的密度作为系统密度,系统密度是出厂预置的,如440dpi的系统密度就是和它最接近的480dpi;如果是330dpi的设备,它的系统密度就是320dpi。但是,现在很多手机不一定会选择这些值作为系统密度,而是选择实际的dpi作为系统密度,这就导致了很多手机的dpi也不是在这些值内。例如小米Note这样的xxhdpi的设备他的系统密度并不是480,而是它的实际密度440。

  • 获取设备的上述属性

Android系统中有个DisplayMetrics的类,通过这个类就可以得到上述的所有属性。

        DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
        float density = displayMetrics.density; //屏幕密度
        int densityDpi = displayMetrics.densityDpi;//屏幕密度dpi
        int heightPixels = displayMetrics.heightPixels;//屏幕高度的像素
        int widthPixels = displayMetrics
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值