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中制定尺寸, 适配屏幕

08,Android 屏幕适配(dp适配+dimens文件)

 

 

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文件

 

08,Android 屏幕适配(dp适配+dimens文件) 

我们先不管这个,仿照系统这个自己创建一个values

选中res文件夹,然后点击右键,选中Android resource directory

08,Android 屏幕适配(dp适配+dimens文件) 

然后在这里给Directory name命名为values-1280x720,这个意思是说,当检测当手机是1280x720的时候,系统会去找此文件夹下面的dimens,而不是默认的values文件夹。

08,Android 屏幕适配(dp适配+dimens文件) 

创建好了之后新建一个dimens文件,结果是这个样子的,如图:

08,Android 屏幕适配(dp适配+dimens文件) 

我们仿照刚才的过程再创建一个values-1920x1080的文件夹。

08,Android 屏幕适配(dp适配+dimens文件) 

 

做好这几个步骤之后,点击values下面的dimens,然后创建一个dimen,如下图所示,我在此创建了一个名为activity_horizontal_width的dimen,值为160dp,如图:

 

08,Android 屏幕适配(dp适配+dimens文件) 

 

同时再打开values-1280x720文件夹下面的dimens,创建一个相同的名为activity_horizontal_width,但是值为180dp,如图:

 

08,Android 屏幕适配(dp适配+dimens文件) 

 

同样的步骤,在values-1920x1080文件夹下面的dimens里也创建一个同样的180dp的dimen

 

08,Android 屏幕适配(dp适配+dimens文件) 

 

做好了这些之后,接下来我们需要在xml布局里引用,还记得之前的TextView的width写的多少吧?

 

之前写的是160dp,是一个固定值,而现在就不能这么写了,我们需要写成“@dimen/activity_horizontal_width”,这个什么意思呢?其实这里只是一个引用,当我们点击想看看具体是多少的值的时候,会发现这样的情况,如图:

 

08,Android 屏幕适配(dp适配+dimens文件) 

 

这个意思就是,当前我们写的“@dimen/activity_horizontal_width”引用了三个地方,问我们想去查看哪一个文件夹下面的dimens。

 

做好了这一切之后,这个TextView的值就是一个变的,下次再运行到手机上的时候,720p手机上运行时TextView的宽度就是180dp,1080p手机上也是180dp,其他的手机就是160dp(因为我们没有创建其他分辨率的文件夹,所以会走默认的values)。

这就达到了指定机型的屏幕适配。