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:
先看看dp的概念:dp,又叫dip(density independent pixel),独立密度像素。
这么解释基本上等于废话,我们来举例说明:
假设现在没有dp,只有px。现在我们在程序中要画一条线,这条线的长度是屏幕宽度的一半。
正好你手头的测试机是320*480的,那你就在代码里写了这条线的长度如下:
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并不能解决所有问题,好在我们绝大部分情况下,不需要画一半的直线,我们更通常的情况,是摆放一个按钮,然后指定这个按钮的尺寸:
在不同的分辨率和dpi的手机上,这个按钮有时候是按照我们预想的大小比例来显示的,有时候则不是,会整体稍小一点,有时候也会整体偏大一点。好在大部分情况下,我们并不在意这一点偏差,所以你看,dp还是可以解决很多问题的。
那如果真的在意这一点偏差呢?或者偏差比我们预想得要大呢?
卖个关子~那就是我们下一讲的问题了,哈哈~
这次我们来讲点跟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还是可以解决很多问题的。
那如果真的在意这一点偏差呢?或者偏差比我们预想得要大呢?
卖个关子~那就是我们下一讲的问题了,哈哈~
相关文章推荐
- 如何在真机上调试Android应用程序(图文详解)
- android加深笔记--IPC通信之Messenger
- BadgeView的使用
- 各种Android Dialog创建及其监听事件实现
- android Intent.ACTION_DATE_CHANGED监听失败
- Android中常见的内存泄漏
- (转载)Android手机开发总结
- 图片加载利器——Picasso
- Android 编译环境创建
- Android研发规范
- 从窗体泄漏谈android:configChanges属性
- Android开发之第三方跳转
- Android的进程回收机制
- android中webview加载html,输入框不能输入内容问题记录
- android四大组件
- Android status icon remove
- android 软键盘的使用
- android:scrollbarStyle属性及滚动条和分割线覆盖问题
- Android Native反调试
- [Android]对MVC和MVP的总结