Android屏幕适配——多分辨率多屏幕密度

为什么要适配,适配的好处等等这里就不说了,直接说我们要怎么适配,请看下面的内容。

1.重要概念

px:pixel,像素Android原生API,UI设计计量单位,如获取屏幕宽高。

屏幕分辨率:指在纵向和横向方向上的像素点数,单位是px,一般显示方式是纵向像素数量*横向像素数量,如1920*1080。

屏幕尺寸:一般是屏幕对角线长度,单位是英寸,常见尺寸有3.5,4.0,4.3,4.7,5.0,6.0等。

屏幕像素密度:ppi pixel per inch的缩写,意思是每英寸屏幕上的像素数,因为屏幕尺寸是商家生产时就规定好的,屏幕尺寸一样的手机,屏幕宽高却不一定一样,所以通常取屏幕对角线像素数量和屏幕尺寸(屏幕对角线长度)来计算屏幕像素密度,计算公式就是通过勾股定理和分辨率计算得到屏幕对角线像素数量,再除以屏幕尺寸。手机参数上也会有这个数值。

dpi:dot per inch点像素密度,它的计算方法也和ppi一样,但从很多方面上,dpi是和ppi有区别的,ppi是用在设备上的单位,比如显示器;而dpi是用在印刷品上的单位,比如要打印一幅地图;在图像上的像素看起来是一个个点或者方块,这时候通常就将两者混用。要注意的是,我们并不能在Android适配时直接使用手机参数上的ppi值,而是使用dpi,Android对dpi根据大小做了规定的分档,以160dpi为基准,分为ldpi(120dpi)、mdpi(160dpi)、hdpi(240dpi)、xhdpi(320dpi)、xxhdpi(480dpi)等,当然现在手机的分辨率和尺寸更加多,像560dpi,600dpi也有,举个例子,Nexus 6 ppi是493,那按道理我们计算出来的dpi也是493,但Android的分档里面并没有493dpi,所以实际上它的dpi是560,而这个值我们是可以在手机的系统文件里面修改的。一定程度上,我们甚至可以说分辨率和适配没有关系,我们需要考虑的是dpi值,而这个值是可以与分辨率没有关系的,是手机厂家设的。

dp/dip:density independent pixels密度无关像素,Android设计的一个单位,它与px存在一个换算关系,Android规定,在160dpi时,1dp等于1px,那么320dpi时,1dp就等于2px,

所以当px换算为dp时,dp =160 * px / dpi;dp换算为px时,px = dp * dpi /160。换算方法代码:

px与dp的相互换算

sp:scale independent pixels比例无关像素,是Android推荐使用的字体大小单位,同样是密度无关,而且看上去似乎使用dp也没问题(以前的Android开发很多是这样写)但是,原因就在比例上,字体除了数值设置外,还受到系统字体大小设置的影响,而使用sp是适应这种变化的,dp则不会跟随系统字体大小设置的变化而变化,所以除非你想字体大小不随着系统字体大小设置变化,字体大小单位都使用sp。但是sp与设计图上px的转换可以使用dp与px的换算公式。


2.适配

适配方案有很多种,比如百分比布局,比如根据每个要适配的屏幕都写一套布局,比如分辨率等比缩放等。但都有这样那样的问题,Apk体积增大,难以维护……我个人比较推荐以下的做法:

多个demins(dp写法)

我们可以把控件的大小数值写在多个dimens xml文件中,让应用显示控件大小的时候像获取图片资源一样,根据规则选择具体的值。而dimens文件在values文件夹下,其实就是应用到不同的values文件夹下的dimens文件中读取到需要的值。但这个“规则”的设置就是最考验适配技巧的时候了,诀窍在于我们怎么去命名values文件夹和对设计稿上控件大小进行符合“规则”的单位换算。让我们来看一下怎么去做?

values文件夹根据限定符去命名

屏幕尺寸:指最短的可用屏幕区域。如sw480dp,表示适配可用屏幕尺寸起码为480dp的情况。

屏幕分辨率:必须较大数值在前,较小数值在后,如1920x1080,表示适配分辨率为1920x1080的情况,其中x是英文字母x而不是乘号。

屏幕像素密度:如mdpi,表示适配屏幕像素密度值近似或等于mdpi(160dpi)的情况。

屏幕方向:如land(横向)、port(竖向)表示适配屏幕方向为land或者port的情况。

版本:vX(X代表版本号,现在是1到23),表示适配SDK版本为X的情况。

还有很多这里就不一一细说了。

限定符可以组合起来使用来限定更精确的情况如:values-mdpi-land-1920×1080-v19,表示适配SDK版本为19,分辨率为1920×1080的横向屏幕的mdpi手机。

学过组合的都知道这里能有多少种限定符组合,而且其中分辨率的值还是不定的,只要有厂家生产不同分辨率的手机,我们就可以有无数种限定符组合,然而,我们并不用惧怕,限定符的适配是向下匹配的,譬如:有values-port-1920x1080的手机屏幕需要适配,当我们建立的values文件夹里面没有一样的时候,就适配到下一级,比如values-port-1280x720(如果有而且是最接近目标的话),如果还没有,一直向下,最后起码能适配到values这个没有限定符的。

这里现在只考虑竖屏的时候(横屏就是增加land限定符,而且数值变化太大,布局也可能需要专门去写,适配的原理还是一样的,这里就以竖屏为例)根据以下的例子:

1.UI给我们做了一套1920x1080的图片,通常将该分辨率的图片放在drawable-xxhdpi的文件夹下,应为通常分辨率为1920x1080的屏幕都是xxhdpi(480dpi)的。

2.这时候,图片上有一个90x30(px)的控件,在1920x1080的机子的布局里面根据换算方法转换成30x10(dp)而xhdpi(320dpi)的1280x720上是多少呢?设在该屏幕上的长为A像素(px),根据比例式,A/720=30/1080,那么就知道A为20px,那么根据换算公式,dp还是10!

3.我们再来看看两个机子它们的sw是多少dp?选短边计算,1080/480/160=360,720/320/160=360,那么结合第二点来看,只要sw相同,无论具体的在屏幕上显示的px是多少,dp都是相同的,dp相同,代表视觉大小是相同的,意味着我们看到的布局效果是一样的,适配解决!

所以我们只需要使用规则给values文件夹命名如下:values-swXXXdp,就可以了。大概像这样:


values文件夹命名

可能有人有疑问了,那么如果遇上一些超级奇葩的厂家给机子设置了很奇葩的dpi值呢,单靠这个规则就真的OK吗?

譬如:遇上分辨率为1980x1080,但dpi是mdpi的屏幕时,这台机子的尺寸就是短边1080/160/160=1080dp,那么我们只需要建立一个values-sw1080dp的文件夹,具体的dp值就是控件长的px值B = 30/1080*1080 = 30,dp = 30 / (160/160 )= 30,这并没有什么问题。

其实可以看出来,这不是分辨率等比缩放的写法吗?只不过把等比缩放之后的分辨率再根据换算方法将px换成dp罢了。但是!分辨率可以有无穷多种,而以下是可以使用的通用屏幕尺寸的一些值:

1.320,针对以下屏幕配置的设备:

240x320ldpi(QVGA手持设备)

320x480mdpi(手持设备)

480x800hdpi(高分辨率手持设备)

2.480,针对480x800mdpi的屏幕(平板或手持设备)

3.600,针对600x1024mdip的屏幕(7英寸平板)

4.720,针对720x1280mdip的屏幕(10英寸平板)

注意:当应用程序提供了多个带有不同值的最小宽度限定符资源目录时,系统会使用最接近(不超出)设备最小宽度的那个资源。这个限定符被添加在API级别13中。还要看android:requiresSmallestWidthDp属性,它声明了与你的应用程序兼容的最小的最小宽度,并且smallestScreenWidthDp配置字段会持有这个设备最小宽度的值。

那么我们的灵活性就大大提高的同时,相对于少则十几多则数十的分辨率种类,会使用近似值的sw-XXXdp写法就只需要少于十种的就可以搞定了。

当然,按照前面说的限定符规则,在sw-XXXdp的基础上,我们还可以加上版本号,屏幕方向去针对某些系统版本的手机或者平板,同样是比使用分辨率的少很多。

最后的问题就是就算要处理的只有几个dimens文件,但每个里面可能有十分多的值,一个个换算,新建,修改,简直是折磨人的,但既然我们知道了换算的规则,知道了dimens的调用规则,写个方法去修改xml的文件内容是很简单的,代码请下载(这里要感谢柯铿!):Android屏幕适配

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容