您的位置:首页 > 移动开发 > Android开发

android屏幕适配终极指南(二):DP和DPI

2015-12-10 16:21 651 查看
上次我们讲了DPI,分辨率的一些事儿(有兴趣的童鞋可以去这里看:android屏幕适配终极指南(一):DPI,分辨率和屏幕尺寸

这次我们来讲点跟android有关的。

大家都知道,一个正常的工程,都会有如下几个文件夹:



ps:旧的版本还会有个drawable-ldpi,也就是low dpi,但是这个在我现在使用的android studio1.0中,创建工程时并没有生成它,我猜测可能是现在的手机基本上不会有ldpi,所以默认不生成这货了。

这几个文件夹是干啥的,我相信各位也知道:不同分辨率下的图片资源放在不同的文件夹下面,来保证不同分辨率下的图片不会变形

我相信你们也在网上找到过各种资料,对这几个文件夹有过如下的描述:

drawable-ldpi: 对应分辨率240*320

drawable-mdpi: 对应分辨率320*480

drawable-hdpi: 对应分辨率480*800

drawable-xhdpi: 对应分辨率720*960

drawable-xxhdpi:对应分辨率720*1280

也就是说,我给一个按钮出5张不同分辨率的图,分别放在这5个文件夹下面,这样手机分辨率就算不一样,按钮也不会变形或者模糊什么的。

那么问题来了,如果我的手机分辨率是500*800,那么它属于哪个?

有人说hdpi,因为最相近,有人说xhdpi,因为超过hdpi的最高值了,其实哪个都有可能,还有可能是xxhdpi呢

所以上面的公式实际上是不对的,或者说,它只是一个通常状况下的公式,但是国内手机生产商什么样的奇葩手机都能生产出来,你还指望有什么”通常状况”。。。

真正的公式如下:

drawable-ldpi (dpi=120, density=0.75)

drawable-mdpi (dpi=160, density=1)

drawable-hdpi (dpi=240, density=1.5)

drawable-xhdpi (dpi=320, density=2)

drawable-xxhdpi (dpi=480, density=3)

也就是说,这5个文件夹,关联的不是分辨率,而是DPI

后面那个density,通常我们叫它”密度因子”。它的计算公式是:DPI/160 = density,是的,你没有看错,就是一个固定值160。为啥要选160呢?

这个在Google的官方文档中有给出了解释,因为第一款Android设备(HTC的T-Mobile G1)是属于160dpi的。

The generalized sizes and densities are arranged around a baseline

configuration that is a normal size and mdpi(medium) density. This

baseline is based upon the screen configuration for the first

Android-powered device, the T-Mobile G1, which has an HVGA screen

(until Android 1.6, this was the only screen configuration that

Android supported).

既然说到了density,那我们就要提一提dp

相信每个开发者都不会陌生,我们在绝大多数情况下,给布局文件里面的控件定义尺寸,都不会直接使用px,而是使用dp:

<WebView
android:id="@+id/webview"
android:layout_width="200dp"
android:layout_height="100dp"/>


先看看dp的概念:dp,又叫dip(density independent pixel),独立密度像素。

这么解释基本上等于废话,我们来举例说明:

假设现在没有dp,只有px。现在我们在程序中要画一条线,这条线的长度是屏幕宽度的一半。

正好你手头的测试机是320*480的,那你就在代码里写了这条线的长度如下:

<ImageView
android:id="@+id/line"
android:layout_width="160px"
android:layout_height="1px"/>


160px,正好等于屏幕宽度的一半。

然后你换一个480*800的手机测试一下吧。

我擦,怎么这条线只占屏幕的1/3了!

很正常,因为你画的线是160px,而在480px的手机上,160/480=1/3

那咋办。。。。

我判断一下,如果手机是480的,我就把width改成240。

那我再换个别的尺寸,你还要改,而且你根本不知道明天会冒出一个什么新的尺寸的手机来。。。。

所以为了减少开发者的工作量,Google提出了dp的概念,dp和px之间的换算公式是:

px = dp * (dpi / 160) = dp * density

ok,现在我们再回到画直线的问题.

我的屏幕是320*480的,所以我的线的长度应该是160px,320*480的分辨率,通常dpi=160,所以也就是 dp = px/(dpi / 160) = 160/(160/160) = 160

现在再拿刚才480*800的手机过来,通常480*800的手机dpi=240,所以代入刚才的dp=160,我们可以得到px=dp * (dpi/ 160)=160*(240/160)=240;也就是说,在 480*800且dpi=240的手机上,线的长度为240px,正好也是屏幕的一半。

你们看,问题现在解决了吧?

其实并没有,你换个别的手机,比如720*1280且dpi=480的试试,你发现还是不等于1/2!!!

咋办?

不咋办,就是这样,如果你要实现一半长的线,应该用别的方法,而不是dp。

所以上面的例子,我主要是要告诉大家,为啥要有dp

**

因为在通常情况下,用dp能省去开发者很大的工作量

**

但是,你也看到了,dp并不能解决所有问题,好在我们绝大部分情况下,不需要画一半的直线,我们更通常的情况,是摆放一个按钮,然后指定这个按钮的尺寸:

<Button
android:id="@+id/button"
android:layout_width="200dp"
android:layout_height="100dp"/>


在不同的分辨率和dpi的手机上,这个按钮有时候是按照我们预想的大小比例来显示的,有时候则不是,会整体稍小一点,有时候也会整体偏大一点。好在大部分情况下,我们并不在意这一点偏差,所以你看,dp还是可以解决很多问题的。

那如果真的在意这一点偏差呢?或者偏差比我们预想得要大呢?

卖个关子~那就是我们下一讲的问题了,哈哈~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: