08,Android 屏幕适配(dp适配+dimens文件)
1,使用方法
-
在程序获取到当前屏幕的dp值
- 设备密度:
float density = getResources().getDisplayMetrics().density;
-
美工提供像素px值, 我们使用前需要用px除以设备密度,转换成dp后,写在布局文件中
dp = px / 设备密度
2,使用的一些技巧
-
常规设备密度: 320x240(0.75), 480x320(1), 800x480(1.5), 1280x720(2)
-
设置dp值, 在不同屏幕上查看显示的比例
-
创建文件夹values-xhdpi, 在dimens.xml中制定尺寸, 适配屏幕
3,dp 适配理解
【1】我们总是在xml布局里写dp,dp到底是什么意思呢?
这是Android开发中特有的一种度量,称作屏幕无关像素,它不表示任何具体的长度或者像素点, 这个值只有在 具体屏幕密度的手机上,才会被转换为具体的像素值。
它跟px不一样,咱们在xml里面写上px,那无论运行到任何设备上,就是固定的px,不会发生什么变化,但是dp就不一样了。
比如拿以下几种来说明一下。
分辨率(px) |
系统密度(dpi) |
240x320 |
120 |
320x480 |
160 |
480x800 |
240 |
720x1280 |
320 |
1080x1920 |
480 |
【2】1dp转换的px是多少呢?
其实就跟dpi有关,而基准线是160dpi,这就意味着1dp在320x480这款手机上就是1px,在480x800是1.5px,720x1280上是2px,1080x1920上是3px。
这就是dp。
比如现在有这么个需求,要求一个控件的宽度占屏幕的一半,我们用dp怎么来实现呢?
首先进行计算,比如320x480,它的宽是320个px,那我们就要写160px,用dp来表示就是160dp。所以我们可以在xml布局里写160dp就可以了,同样的方式试一试其他的手机:
比如240x320,你写160dp在这种手机上转换的px就是
160dp*120/160 = 120px,所以在这种手机上160dp代表的就是120px,刚好是240的一半,也能适配。
再来试一试480x800,想在这种手机上也占一半,必须是240px,而咱们写的是160dp,它转换的px就是 160dp*240/160=240px,刚好也能符合需求。
其实Google出dp这个东西本身就能达到适配的概念,你看,咱们写了一个160dp,跑到这几种手机上都能达到需求,这不就是适配了吗?
但是我之所以提出来了,就说明dp并不能保证适配,比如咱们试试720x1280。
720的一半是360px,而咱们写的160dp,转换的px是160dp*320/160=320px,明显就不是一半,差了40px。也就是说咱们的代码运行到这种手机上的时候就没有适配好,没有达到需求。
再试试1080x1920的,同样的计算,160dp*480/160=480,而1080的一半是540,480跟540差了60px,也不行,没有达到需求。
由此可见,当在240x320,320x480,480x800上面的时候写160dp是正常的,可以满足需求。而在720x1280,1080x1920上面却不能完美适配。
问题抛出来了,该怎么解决这个问题呢?
比如720p和1080p,我们通过计算,720/2=360,而根据dpi的比例320/160=2,所以我们要想再720p的手机上占宽度的一半,dp值应该是360px/2=180dp。
反过来算一下,如果我们写180dp,那在720p上转换的像素是180dp*320/160=360px,是720的一半,换到1080p上,180dp*480/160=540px,刚好是1080的一半,那也就是说,咱们写180dp就可以实现了需求,那咱们就可以在xml布局里这么写:
<TextView
android:layout_width="180dp"
android:layout_height="wrap_content" />
可是,这么一写又有问题出现了,在240x320,320x480,480x800上面又坏了,这可怎么办呢?
【3】千呼万唤始出来,dimens+dp
我的天,说了这么多废话终于到正题了。
Android 的values文件夹下面可以创建一个dimens的文件。这个dimens的作用就跟mipmap和drawable的引用方式一样,可以通过@dimens/xxx的方式来引用。我们的思路就是创建多套dimens,然后xml布局引用dimens,当运行到不同的手机上时,系统会自动去寻找相应的dimens,去加载我们提前准备好的dp值,图文教程:
首先,系统默认的values下面就有个dimens文件
我们先不管这个,仿照系统这个自己创建一个values
选中res文件夹,然后点击右键,选中Android resource directory
然后在这里给Directory name命名为values-1280x720,这个意思是说,当检测当手机是1280x720的时候,系统会去找此文件夹下面的dimens,而不是默认的values文件夹。
创建好了之后新建一个dimens文件,结果是这个样子的,如图:
我们仿照刚才的过程再创建一个values-1920x1080的文件夹。
做好这几个步骤之后,点击values下面的dimens,然后创建一个dimen,如下图所示,我在此创建了一个名为activity_horizontal_width的dimen,值为160dp,如图:
同时再打开values-1280x720文件夹下面的dimens,创建一个相同的名为activity_horizontal_width,但是值为180dp,如图:
同样的步骤,在values-1920x1080文件夹下面的dimens里也创建一个同样的180dp的dimen
做好了这些之后,接下来我们需要在xml布局里引用,还记得之前的TextView的width写的多少吧?
之前写的是160dp,是一个固定值,而现在就不能这么写了,我们需要写成“@dimen/activity_horizontal_width”,这个什么意思呢?其实这里只是一个引用,当我们点击想看看具体是多少的值的时候,会发现这样的情况,如图:
这个意思就是,当前我们写的“@dimen/activity_horizontal_width”引用了三个地方,问我们想去查看哪一个文件夹下面的dimens。
做好了这一切之后,这个TextView的值就是一个变的,下次再运行到手机上的时候,720p手机上运行时TextView的宽度就是180dp,1080p手机上也是180dp,其他的手机就是160dp(因为我们没有创建其他分辨率的文件夹,所以会走默认的values)。
这就达到了指定机型的屏幕适配。