Android 屏幕适配相关知识

这周第一次接触了视觉交互部门的稿件,要根据那边制定的视觉规范,编写适应所有Android机型的XML布局文件。这篇博客把自己学到的Android适配相关的知识记录下来,以便日后开发时查阅。

基础知识

Android屏幕适配相关的一些基本概念:

像素:px

是英文单词pixel的缩写,意为像素,屏幕上的点。我们通常所说的分辨率如480X800就是指的像素。在设计领域中,像素是用来计算数码影像的最小单位。计算机中显示的图像并非连续的线条组成,而是由许多肉眼看不见的小点组成。如果把影像放大数倍,会发现这些连续色调其实是由许多色彩相近的小点所组成,这些小点就是构成影像的最小单位“像素”。由于是最小的独立显示单位,px均为整数,不会出现0.5px的情况。

英寸: in

是英文单词inch的缩写,意为英寸,是一种长度单位。通常我们所说的手机屏幕大小如4英寸,4.3英寸,5.5英寸指的是手机屏幕对角线的长度,即要通过手机的长宽和勾股定理计算得出。

dpi/ppi

是英文单词dots/pixels per inch,即每英寸 像素/点 的数目,计算公式比较复杂,对手机的屏幕分辨率分辨率进行平方和后开方除以手机的尺寸。举个例子,手机分辨率为320*480,宽为 2 inch,长为 3 inch,那么它的dpi计算如下: dpi = √(320^2 + 480^2)/√(2^2 + 3^2) ≈ 160

density

顾名思义,desity代表屏幕密度,计算方法很简单,把dpi除以160即可

dip(简称dp)

是英文单词device independent pixel。是Android为了适配不同分辨率不同尺寸的屏幕,而发明出来的尺寸标准。在屏幕密度dpi = 160屏幕上,1dp = 1px。

为什么要引入dp这个概念

视觉交互给我的设计稿长度尺寸单位均为px,那么为什么我们不能再定义布局文件时直接使用px呢,原因见下图:
这里写图片描述
如图所示,当我们把屏幕上某个图形不断放大时,会发现这些图形是由一个一个很小的点组成的,即上文所述的屏幕最小描述单位像素。像素的多少可以最直观的反映到手机或者电脑的屏幕上。当我们在开发的过程中,定义一个布局文件时,如果直接采用px为长度尺寸时,会发生如下图所示的问题:
这里写图片描述
虽然我们在布局文件中定义的尺寸时固定的像素个数,但是由于不同的屏幕像素密度(dpi)不一样,产生相同的像素个数需要的屏幕大小也不同(类似于一公斤棉花和一公斤铁,虽然重量一样,但由于密度不同,所需要的体积也不一样)。

而像素密度是由屏幕尺寸和屏幕分辨率共同决定的,所以只满足这两个条件之一,相同像素产生的视觉效果也会有不同。图一图二屏幕尺寸相同,图二图三屏幕分辨率相同,但是最终的视觉效果差别很大。

这样的差异会导致在不同的手机上运行相同的APP,产生很大的差别,甚至影响用户的使用,所以为了适配不同的屏幕,Android引入了dp的概念,来确保我们所编写的布局文件适应不同的手机。

dp是如何进行屏幕适配的

由之前所述的dpi计算公式,我们可以计算得到上图三部手机的dpi分别为217、342、267。对比上图可知,dpi越低图片显示的越大,dpi越高图片显示的越小。假设现在我们指定屏幕上的图标宽为40dp。

对于屏幕1来说,屏幕密度为dpi/160 = 1.35,那么40dp约为40*1.35=54.25px。已知该屏幕宽为480px,那么此时约占该屏幕的54/480≈0.11.

对于屏幕2来说,屏幕为dpi/160约为2,那么40dp约为40*2=80px。已知该屏幕宽为720px,那么此时约为该屏幕的80/720≈0.11.

对于屏幕3来说,屏幕为dpi/160约为1.67,那么40dp约为40*1.67=66.75px。已知该屏幕宽为720px,那么此时约为该屏幕的66.75/720≈0.09.

但是屏幕3的实际尺寸比前两个屏幕要大,所以最后综合来看,三个屏幕的图标会呈现相近的大小。如图:
这里写图片描述

总结:如果屏幕密度为160,这时dp和sp和px是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成160px,在密度为320的3.2 寸屏幕里看要比在密度为160的3.2寸屏幕上看短了一半。但如果设置成160dp或160sp的话。系统会自动将width属性值设置成320px的。也就是160 * 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dp和sp,系统会根据屏幕密度的变化自动进行转换。

实际开发

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)

上面五种是Android手机中比较常用的五种屏幕类型。市面上的一些Android教程大多都是教的是为每种dpi都出一套图片资源,这个固然是一种解决办法,但同时也是一种非常笨的方法,为美工或者设计增加了不少的工作量不说,同时也会让你的apk包变的很大。那么有没有什么好的方法既能保证屏幕适配,又可以最小占用设计资源,同时最好又只使用一套dpi的图片资源呢?下面就来讲解下项目中总结出来的这个方法。

首先必须清楚一个自动渲染的概念,Android SDK会自动屏幕尺寸选择对应的资源文件进行渲染,如SDK检测到你手机dpi是160的话会优先到drawable-mdpi文件夹下找对应的图片资源,注意只是优先,假设你手机dpi是160,但是你只在xhpdi文件夹下有对应的图片资源文件,程序一样可以正常运行。所以理论上来说只需要提供一种规格的图片资源就ok了,如果只提供ldpi规格的图片,对于大分辨率的手机如果把图片放大就会不清晰,所以需要提供一套你需要支持的最大dpi的图片,这样即使用户的手机分辨率很小,这样图片缩小依然很清晰。

上面说了只需要提供一套大的dpi的图片就ok了,现在市面手机分辨率最大可达到1080X1920的分辨率,如Nexus5,dpi属于xxhdpi,但是毕竟还没普及,目前市面上最普遍的高端机的分辨率还多集中在720X1080范围,也就是多集中在xhdpi,所以目前来看xhpdi规格的图片成为了首选。当然随着技术规格的提高以后发展,以后可能市场上xxdpi的手机会越来越普遍,但这是后话。

在现在的App开发中,基本都会有iOS和Android版本,有些公司为了保持App不同版本的体验交互一致,还有些公司的设计资源可能比较紧张,这些情况下iOS和Android版本基本是一个设计师主导,而大多数情况下设计师可能更会以iPhone手机为基础进行设计,包括后期的切图之类的。这个时候身为Android开发人员你是否还要求设计师单独为Android端切一套图片资源呢?这会让你们的设计师崩溃的,下面就来告诉一个项目中总结的更棒的方法。

相信设计师们一般都会用最新的iPhone6来做原型设计,根据勾股定理√(750^2+1334^2)≈1530.37,1530.37/4.7≈325.61, 刚好属于xhdpi,所以你可以很自豪的像你们的设计师说不用专门为Android端切图,直接把iPhone的那一套切好的图片资源放入drawable-xhdpi文件夹里就ok了。

dp和sp的关系

首先,我们可以看一下px分别换算成dp和sp的代码:

//px转换成sp
public static int px2sp(Context context, float pxValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (pxValue / fontScale + 0.5f);
    }
//px转换成dp
public static int px2dp(Context context, float px) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (px / scale + 0.5f);
    }

从代码来看,仅仅只有scaledDensity和density两个量有所不同,我们可以看一下源码中对这scaledDensity的描述:

/**
     * A scaling factor for fonts displayed on the display.  This is the same
     * as {@link #density}, except that it may be adjusted in smaller
     * increments at runtime based on a user preference for the font size.
     */

大体的意思是指:默认情况下这scaledDensity与density是相同的,只有在用户对手机上的字体大小进行设置后,才会有不同。所以在实际开发中,如果我们不希望因为用户设置而改变我们开发的APP视觉效果,应该在开发时统一设定字体大小单位均为dp。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值