关于Android屏幕适配这一块网上有很多文章讲解,看完后收益匪浅,怕自己看完后又会忘记所以写下自己的一些见解和认识
基本概念知识
1、常用单位及其关系
px:像素
inch:英寸
pt:1/72 英寸
dpi:一英寸长的直线上的像素点的数量,即像素密度。不同的设备,dpi值不同,显示效果不同,dpi的值跟设备硬件有关。标准值是160dp。
dp(dip):独立像素密度。即在标准屏幕下,1个像素点的长度,标准屏幕是160dpi,可以理解为1英寸长度上有160个像素。标准屏幕中1dp=1px。
px = dp*(dpi/160);//当dpi=160时,1px=1dp
分辨率:屏幕上长宽方向上像素点的数量,即一个屏幕上像素的数量。
例如:720*1280 = 屏幕x轴上有720个像素,屏幕y轴上有1280个像素
分辨率单位:dpi(点每英寸)、lpi(线每英寸)、ppi(像素每英寸)
屏幕的物理尺寸:屏幕对角线的长度,单位是inch
sp:专用于设定文字大小,受dpi影响和用户的字体偏好设定影响。
2、获取手机的设备的配置信息
DisplayMetrics d = getResources().getDisplayMetrics();//可以获得scaledDensity,densityDpi,heightPixels,widthPixels等信息。
Configuration configuration = getResources().getConfiguration();//获取设备的配置信息
// configuration.screenHeightDp //当前屏幕可用空间的高度,单位是dp
// configuration.screenWidthDp //当前屏幕可用空间的宽度,单位是dp
int densityDpi = configuration.densityDpi;//当前设备的dpi信息
下图是我debug时获取的手机设备的信息
例子:
已知设备1080x1920,使用DisplayMetrics获取的实际信息是1080*1812,y轴方向上的像素有误差是因为软键盘,实际屏幕要小。
使用Configuration获取的设备的dpi=480dpi,根据公式px=dp*(dpi/160)。
现在px=1080,dpi=480,则dp=360.
使用configuration.screenWidthDp得到的数值为360,和上面用公式算出的一致。
项目下文件mdpi、hdpi、xdpi、xxdpi、xxxdpi
名称 | 像素密度范围 | 图标尺寸 | 比例 |
---|---|---|---|
mdpi | 120dpi~160dpi | 48x48px | 1 |
hdpi | 160dpi~240dpi | 72x72px | 1.5 |
xhdpi | 240dpi~320dpi | 96x96px | 2 |
xxhdpi | 320dpi~480dpi | 144x144px | 3 |
xxxhdpi | 480dpi~640dpi | 192x192px | 4 |
看着上面的表格先不说别的,就这个比例,就可以知道标准dpi对应的就是mdpi,现在的的手机起码也有320dpi以上吧。所以接下来就分析这几个dpi对应的文件夹作用
项目下文件mdpi、hdpi、xdpi、xxdpi、xxxdpi在手机下的显示和作用
刚刚debug可以看到我的手机的dpi也就是xxhdpi,比例是3,下面看我的代码:
布局文件
代码文件
setContentView(R.layout.activity_main);
ivImage = (ImageView) findViewById(R.id.iv);
tvImageInfo = (TextView) findViewById(R.id.tv_imageInfo);
findViewById(R.id.bt_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tvImageInfo.setText("图片宽度:" + ivImage.getWidth() + " 图片高度:"+ivImage.getHeight());
}
});
资源文件
步骤一
我把一张200x200的图片放在xxhdpi里,按照之前的想法判断,我的手机因为是480dpi当然会直接去找自己对应的文件夹去拿图片,没错,找到图片,然后显示,然后我们点击获取图片的宽高,果然是200x200,不信看图:
为什么这样呢,因为我的手机找到对应对的图片,所以毫不犹豫的完完全全的显示出来!
步骤二
我把我的这样图片放在hdpi这个文件夹下,不贴图了,其他的不变,我们来看看效果:
可以看到明显比刚才放大一倍,为什么呢,从对应的关系知道xxhdpi对应的比例是3,而hdpi对应的比例是1.5,正好是两倍的差距,为什么这样呢,我来解释:我的手机对应的是xxhdpi自然去xxdpi里找,没有的话就直接去比它更高密度文件去找如:xxxhdpi>xxxxhdpi按照依次递增的去找,如果没有的话就去找自己的drawable,如果也没有就向下按照顺序找:xhdpi>hdpi>mdpi>ldpi,最后总会找到吧,在hpi里找到后,但是系统会认为你这张图是专门为低密度的设备所设计的,如果直接将这张图在当前的高密度设备上使用就有可能会出现像素过低的情况,于是系统自动帮我们做了这样一个放大操作。
步骤三
同理可知 如果系统是在drawable-xxxhdpi文件夹下面找到这张图的话,它会认为这张图是为更高密度的设备所设计的,如果直接将这张图在当前设备上使用就有可能会出现像素过高的情况,于是会自动帮我们做一个缩小的操作。我们把图片放到xxxhpi里,没猜错的话图片会缩小按照表格比例是:3/4,看图来:
步骤四
我如果把布局文件的宽高写死呢:那我现在都写成高:200dp 宽:200dp,然后把图片依次按照刚才放的顺序来一次
但是我发现我所有的显示都如下:
有没发现图片都是600x600,因为从debug知道我的手机宽是360dp 按照比例200dp是屏幕的:5/9,我的手机宽是1080px,那5/9正好是:600px,哈哈哈,果然是。
步骤五
我来换个手机试试:我的红米note2两年前的,还不错。
照例我debug还打印出手机信息:
可以看到我的手机dpi是320,属于xhdpi,刚刚的xml中wrap_content的效果我不测试了,效果和上面一样,我来测试如果我写死宽高都为200dp,来看看效果:
可以看到宽高都为400,红米手机的宽为360dp 按照比例200dp是屏幕的:5/9,我的手机宽是720px,那5/9正好是:400px,有没发现我的两个手机宽都是相同的360dp,为什么呢,道理很简单套用之前的公式:px = dp*(dpi/160),所以啊,根据一次函数就可以得出他们具有相同的宽高dp,所有手机的宽高dp和他们的分辨率和dpi有关系,和物理尺寸没关系,当然这个理论是我自己的出来的!不信我,我换个5.0的手机测试下
我现在弄个5.0的Nexus 5来做以上红米手机的同样操作,先看看debug信息:
可以看到同样的分辨率同样的dpi,同样的宽度dp,至于图片的显示宽度,不用说都是600px,我上图:
那我再弄个模拟器实验下4.0尺寸分辨率:480x800:
可以看到分辨率小很多,宽是320dp,按照写死的200dp,比例得出的应该是宽480的5/8,那就是300px,上图:
验证,和开发时运用
通过以上的图片例子可以知道,图片在手机显示的尺寸,只要给一个固定的宽高,它就会按照屏幕的比例去显示,现在市面上的手机大多,根据最后的公式的出来的宽度基本都是360dp,所以在开发中用dp,就会解决很多适配问题,至于其他的布局就要灵活运用了,至于图片放在哪个文件下,还有适配问题xml布局,这些网上都有很好解决办法!
结论
本文最主要的是认识我们常说的这些分辨率,和密度,这些关系