1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 今日头条适配方案

今日头条适配方案

时间:2020-02-24 18:02:10

相关推荐

今日头条适配方案

前言

这个月在Android技术圈中屏幕适配这个词曝光率挺高的,为什么这么说呢?因为这个月陆续有多个大佬发布了屏幕适配相关的文章,公布了自己认可的屏幕适配方案

上上个星期Blankj老师发表了一篇力挺今日头条屏幕适配方案的 文章,提出了很多优化的方案,并开源了相关源码

上个星期拉丁吴老师在鸿神的公众号上发布了一篇 文章,详细描述了市面上主流的几种屏幕适配方案,并发布了他的smallestWidth限定符适配方案和相关源码 (其实早就发布了),文章写的很好,建议大家去看看

其实大家最关注的不是市面上有多少种屏幕适配方案,而是自己的项目该选择哪种屏幕适配方案,可以看出两位老师最终选择的屏幕适配方案都是不同的

我下面就来分析分析,我作为一个才接触这两个屏幕适配方案的吃瓜群众,我是怎么来验证这两种屏幕适配方案是否可行,以及怎样根据它们的优缺点来选择一个最适合自己项目的屏幕适配方案

这是我推荐给大家的屏幕适配框架,本来想放到最后作为福利的,害怕大家看不到,所以就将链接放到这里,提前送给大家

Github : 您的 Star 是我坚持的动力 ✊

浅谈适配方案

拉丁吴老师的文章中谈到了两个比较经典的屏幕适配方案,在我印象中十分深刻,我想大多数兄弟都用过,在我的开发生涯里也是有很长一段时间都在用这两种屏幕适配方案

第一种就是宽高限定符适配,什么是宽高限定符适配呢

├── src/main│ ├── res│ ├── ├──values│ ├── ├──values-800x480│ ├── ├──values-860x540│ ├── ├──values-1024x600│ ├── ├──values-1024x768│ ├── ├──...│ ├── ├──values-2560x1440复制代码

就是这种,在资源文件下生成不同分辨率的资源文件,然后在布局文件中引用对应的dimens,大家一定还有印象

第二种就是鸿神AndroidAutoLayout

这两种方案都已经逐渐退出了历史的舞台,为什么想必大家都知道,不知道的建议看看拉丁吴老师的文章,所以这两种方案我在文章中就不在阐述了,主要讲讲现在最主流的两种屏幕适配方案,今日头条适配方案 和smallestWidth限定符适配方案

建议大家不清楚这两个方案的先看看这两篇文章,才清楚我在讲什么,后面我要讲解它们的原理,以及验证这两种方案是否真的可行,最后对他们进行深入对比,对于他们的一些缺点给予对应的解决方案,绝对干货

今日头条屏幕适配方案

原理

上面已经告知,不了解这两个方案的先看看上面的两篇文章,所以这里我就假设大家已经看了上面的文章或者之前就了解过这两个方案,所以在本文中我就不再阐述DPIDensity以及一些比较基础的知识点,上面的文章已经阐述的够清楚了

今日头条屏幕适配方案的核心原理在于,根据以下公式算出density

当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density

density的意思就是1 dp占当前设备多少像素

为什么要算出density,这和屏幕适配有什么关系呢?

public static float applyDimension(int unit, float value,DisplayMetrics metrics){switch (unit) {case COMPLEX_UNIT_PX:return value;case COMPLEX_UNIT_DIP:return value * metrics.density;case COMPLEX_UNIT_SP:return value * metrics.scaledDensity;case COMPLEX_UNIT_PT:return value * metrics.xdpi * (1.0f/72);case COMPLEX_UNIT_IN:return value * metrics.xdpi;case COMPLEX_UNIT_MM:return value * metrics.xdpi * (1.0f/25.4f);}return 0;}复制代码

大家都知道,不管你在布局文件中填写的是什么单位,最后都会被转化为px,系统就是通过上面的方法,将你在项目中任何地方填写的单位都转换为px

所以我们常用的pxdp的公式dp = px / density,就是根据上面的方法得来的,density在公式的运算中扮演着至关重要的一步

要看懂下面的内容,还得明白,今日头条的适配方式,今日头条适配方案默认项目中只能以高或宽中的一个作为基准,进行适配,为什么不像AndroidAutoLayout一样,高以高为基准,宽以宽为基准,同时进行适配呢

这就引出了一个现在比较棘手的问题,大部分市面上的Android设备的屏幕高宽比都不一致,特别是现在大量全面屏的问世,这个问题更加严重,不同厂商推出的全面屏手机的屏幕高宽比都可能不一致

这时我们只以高或宽其中的一个作为基准进行适配,就会有效的避免布局在高宽比不一致的屏幕上出现变形的问题

明白这个后,我再来说说densitydensity在每个设备上都是固定的,DPI / 160 = density屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度

设备 1,屏幕宽度为1080px480DPI,屏幕总dp宽度为1080 / (480 / 160) = 360dp

设备 2,屏幕宽度为1440560DPI,屏幕总dp宽度为1440 / (560 / 160) = 411dp

可以看到屏幕的总dp宽度在不同的设备上是会变化的,但是我们在布局中填写的dp值却是固定不变的

这会导致什么呢?假设我们布局中有一个View的宽度为100dp,在设备 1 中 该View的宽度占整个屏幕宽度的27.8%(100 / 360 = 0.278)

但在设备 2 中该View的宽度就只能占整个屏幕宽度的24.3%(100 / 411 = 0.243),可以看到这个View在像素越高的屏幕上,dp值虽然没变,但是与屏幕的实际比例却发生了较大的变化,所以肉眼的观看效果,会越来越小,这就导致了传统的填写dp的屏幕适配方式产生了较大的误差

这时我们要想完美适配,那就必须保证这个View在任何分辨率的屏幕上,与屏幕的比例都是相同的

这时我们该怎么做呢?改变每个Viewdp值?不现实,在每个设备上都要通过代码动态计算Viewdp值,工作量太大

如果每个Viewdp值是固定不变的,那我们只要保证每个设备的屏幕总dp宽度不变,就能保证每个View在所有分辨率的屏幕上与屏幕的比例都保持不变,从而完成等比例适配,并且这个屏幕总dp宽度如果还能保证和设计图的宽度一致的话,那我们在布局时就可以直接按照设计图上的尺寸填写dp

屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度

在这个公式中我们要保证屏幕的总 dp 宽度设计图总宽度一致,并且在所有分辨率的屏幕上都保持不变,我们需要怎么做呢?屏幕的总 px 宽度每个设备都不一致,这个值是肯定会变化的,这时今日头条的公式就派上用场了

当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density

这个公式就是把上面公式中的屏幕的总 dp 宽度换成设计图总宽度,原理都是一样的,只要density根据不同的设备进行实时计算并作出改变,就能保证设计图总宽度不变,也就完成了适配

验证方案可行性

上面已经把原理分析的很清楚了,很多文章只是一笔带过这个公式,公式虽然很简单但我们还是想晓得这是怎么来的,所以我就反向推理了一遍,如果还是看不懂,那我只能说我尽力了,原理讲完了,那我们再来现场验证一下这个方案是否可行?

假设设计图总宽度为375 dp,一个View在这个设计图上的尺寸是50dp * 50dp,这个View的宽度占整个设计图宽度的13.3%(50 / 375 = 0.133),那我们就来验证下在使用今日头条屏幕适配方案的情况下,这个View与屏幕宽度的比例在分辨率不同的设备上是否还能保持和设计图中的比例一致

验证设备 1

屏幕总宽度为1080 px,根据今日头条的的公式求出density1080 / 375 = 2.88 (density)

这个50dp * 50dpView,系统最后会将高宽都换算成px50dp * 2.88 = 144 px(根据公式dp * density = px)

144 / 1080 = 0.133View实际宽度与屏幕总宽度的比例和View在设计图中的比例一致 (50 / 375 = 0.133),所以完成了等比例缩放

某些设备总宽度为1080 px,但是DPI可能不同,是否会对今日头条适配方案产生影响?其实这个方案根本没有根据DPI求出density,是根据自己的公式求出的density,所以这对今日头条的方案没有影响

上面只能确定在所有屏幕总宽度为1080 px的设备上能完成等比例适配,那我们再来试试其他分辨率的设备

验证设备 2

屏幕总宽度为1440 px,根据今日头条的的公式求出density1440 / 375 = 3.84 (density)

这个50dp * 50dpView,系统最后会将高宽都换算成px50dp * 3.84 = 192 px(根据公式dp * density = px)

192 / 1440 = 0.133View实际宽度与屏幕总宽度的比例和View在设计图中的比例一致 (50 / 375 = 0.133),所以也完成了等比例缩放

两个不同分辨率的设备都完成了等比例缩放,证明今日头条屏幕适配方案在不同分辨率的设备上都是有效的,如果大家还心存疑虑,可以再试试其他分辨率的设备,其实到最后得出的比例不会有任何偏差, 都是0.133

优点

使用成本非常低,操作非常简单,使用该方案后在页面布局时不需要额外的代码和操作,这点可以说完虐其他屏幕适配方案

侵入性非常低,该方案和项目完全解耦,在项目布局时不会依赖哪怕一行该方案的代码,而且使用的还是Android官方的API,意味着当你遇到什么问题无法解决,想切换为其他屏幕适配方案时,基本不需要更改之前的代码,整个切换过程几乎在瞬间完成,会少很多麻烦,节约很多时间,试错成本接近于 0

可适配三方库的控件和系统的控件(不止是是ActivityFragmentDialogToast等所有系统控件都可以适配),由于修改的density在整个项目中是全局的,所以只要一次修改,项目中的所有地方都会受益

不会有任何性能的损耗

缺点

暂时没发现其他什么很明显的缺点,已知的缺点有一个,那就是第三个优点,它既是这个方案的优点也同样是缺点,但是就这一个缺点也是非常致命的

只需要修改一次density,项目中的所有地方都会自动适配,这个看似解放了双手,减少了很多操作,但是实际上反应了一个缺点,那就是只能一刀切的将整个项目进行适配,但适配范围是不可控的

这样不是很好吗?这样本来是很好的,但是应用到这个方案是就不好了,因为我上面的原理也分析了,这个方案依赖于设计图尺寸,但是项目中的系统控件、三方库控件、等非我们项目自身设计的控件,它们的设计图尺寸并不会和我们项目自身的设计图尺寸一样

当这个适配方案不分类型,将所有控件都强行使用我们项目自身的设计图尺寸进行适配时,这时就会出现问题,当某个系统控件或三方库控件的设计图尺寸和和我们项目自身的设计图尺寸差距非常大时,这个问题就越严重

举个栗子

假设一个三方库的View,作者在设计时,把它设计为100dp * 100dp,设计图的最大宽度为1000dp,这个View在设计图中的比例是100 / 1000 = 0.1,意思是这个View的宽度在设计图中占整个宽度的10%,如果我们要完成等比例适配,那这个三方库View在所有的设备上与屏幕的总宽度的比例,都必须保持在10%

这时在一个使用今日头条屏幕适配方案的项目上,设置的设计图最大宽度如果是1000dp,那这个三方库View,与项目自身都可以完美的适配,但当我们项目自身的设计图最大宽度不是1000dp,是500dp时,100 / 500 = 0.2,可以看到,比例发生了较大的变化,从10%上升为20%,明显这个三方库View高于作者的预期,比之前更大了

这就是两个设计图尺寸不一致导致的非常严重的问题,当两个设计图尺寸差距越大,那适配的效果也就天差万别了

解决方案

方案 1

调整设计图尺寸,因为三方库可能是远程依赖的,无法修改源码,也就无法让三方库来适应我们项目的设计图尺寸,所以只有我们自身作出修改,去适应三方库的设计图尺寸,我们将项目自身的设计图尺寸修改为这个三方库的设计图尺寸,就能完成项目自身和三方库的适配

这时项目的设计图尺寸修改了,所以项目布局文件中的 dp 值,也应该按照修改的设计图尺寸,按比例增减,保持与之前设计图中的比例不变

但是如果为了适配一个三方库修改整个项目的设计图尺寸,是非常不值得的,所以这个方案支持以Activity为单位修改设计图尺寸,相当于每个Activity都可以自定义设计图尺寸,因为有些Activity不会使用三方库View,也就不需要自定义尺寸,所以每个Activity都有控制权的话,这也是最灵活的

但这也有个问题,当一个Activity使用了多个设计图尺寸不一样的三方库View,就会同样出现上面的问题,这也就只有把设计图改为与几个三方库比较折中的尺寸,才能勉强缓解这个问题

方案 2

第二个方案是最简单的,也是按Activity为单位,取消当前Activity的适配效果,改用其他的适配方案

使用中的问题

有些文章中提到了今日头条屏幕适配方案可以将设计图尺寸填写成以px为单位的宽度和高度,这样我们在布局文件中,也就能直接填写设计图上标注的px值,省掉了将px换算为dp的时间 (大部分公司的设计图都只标注px值),而且照样能完美适配

但是我建议大家千万不要这样做,还是老老实实的以dp为单位填写dp值,为什么呢?

直接填写px虽然刚开始布局的时候很爽,但是这个坑就已经埋上了,会让你后面很爽,有哪些坑?

第一个坑

这样无疑于使项目强耦合于这个方案,当你遇到无法解决的问题想切换为其他屏幕适配方案的时候,layout文件里曾经填写的px值都会作为dp

比如你的设计图实际宽度为1080px,你不换算为360dp (1080 / 3 = 360),却直接将1080px作为这个方案的设计图尺寸,那你在layout文件中,填写的也都是设计图上标注的px值,但是单位却是dp

一个在设计图上300px * 300pxView,你可以直接在layout文件中填写为300dp,而由于这个方案可以动态改变density的原因还是可以做到等比例适配,非常爽!

但你不要忘了,这样你就强耦合于这个方案了,因为当你不使用这个方案时,density是不可变的!

举个栗子

使用这个方案时,在屏幕宽度为1080px的设备上,将设计图宽度直接填写为1080,根据今日头条公式

当前设备屏幕总宽度 / 设计图总宽度 = density

这时得出density为 1 (1080 / 1080 = 1),所以你在layout文件中你填写的300dp最后转换为px也是300px(300dp * 1 = 300px根据公式dp * density = px)

在这个方案的帮助下非常完美,和设计图一模一样完成了适配

但当你不使用这个方案时,density的换算公式就变为官方的DPI / 160 = density, 在这个屏幕宽度为1080px480dpi的设备上,density就固定为 3 (480 / 160 = 3)

这时再来看看你之前在layout文件中填写的dp,换算成px900 px(300dp * 3 = 900px根据公式dp * density = px)

原本在在设计图上为300pxView,这时却达到了惊人的900px,3倍的差距,恭喜你,你已经强耦合于这个方案了,你要不所有layout文件都改一遍,要不继续使用这个方案

第二个坑

第二个坑其实就是刚刚在上面说的今日头条适配方案的缺点,当某个系统控件或三方库控件的设计图尺寸和和我们项目自身的设计图尺寸差距非常大时,这个问题就越严重

你如果直接填写以px为设计图的尺寸,这不用想,肯定和所有的三方库以及系统控件的设计图尺寸都不一样,而且差距都非常之大,至少两三倍的差距,这时你在当前页面弹个Toast就可以明显看到,比之前小很多,可以说是天差万别,用其他三方库View,也是一样的,会小很多

因为你以px为单位填写设计图尺寸,人家却用的dp,差距能不大吗,你如果老老实实用dp,哪怕三方库的设计图尺寸和你项目自身的设计图尺寸不一样,那也差距不大,小到一定程度,基本都不用调整,可以忽略不计,而且很多三方库的设计图尺寸其实也都是那几个大众尺寸,很大可能和你项目自身的设计图尺寸一样

总结

可以看到我讲的非常详细,可以说比今日头条官方以及任何博客写的都清楚,从原理到优缺点再到解决方案一应俱全,因为篇幅有限,如果我还想把smallestWidth限定符适配方案写的这么详细,那估计这篇文章得有一万字了

所以我把这次的屏幕适配文章归位一个系列,一共分为三篇,第一篇详细的讲今日头条屏幕适配方案,第二篇详细的讲smallestWidth 限定符适配方案,第三篇详细讲两个方案的深入对比以及如何选择,并发布我根据今日头条屏幕适配方案优化的屏幕适配框架AndroidAutoSize

今日头条屏幕适配方案官方公布的核心源码只有 30 行不到,但我这个框架的源码有1500行以上,在保留原有特性的情况下增加了不少功能和特性,功能增加了不少,但是使用上却变简单了

<manifest><application> <meta-dataandroid:name="design_width_in_dp"android:value="360"/><meta-dataandroid:name="design_height_in_dp"android:value="640"/> </application> </manifest>复制代码

只要这一步填写了设计图的高宽以dp为单位,你什么都不做,框架就开始适配了

大家可以提前看看我是怎么封装和优化的,我后面的第三篇文章会给出这个框架的原理分析,敬请期待

关于大家的评论以及关注的问题,我在这里统一回复一下:

感谢,大家的关注和回复,我介绍这个今日头条的屏幕适配方案并不是说他有多么完美,只是他确实有效而且能帮我们减少很多开发成本

对于很多人说的DPI的存在,不就是为了让大屏能显示更多的内容,如果一个大屏手机和小屏手机,显示的内容都相同,那用户买大屏手机又有什么意义呢,我觉得大家对DPI的理解是对的,这个观点我也是认同的,Google设计DPI时可能也是这么想的,但是有一点大家没考虑到,Android的碎片化太严重了

为什么Android诞生这么多年,Android的百分比库层出不穷,按理说他们都违背了上面说的这个理念,但为什么还有这么多人去研究百分比库通过各种方式去实现百分比布局?为什么?很简单,因为需求啊!为什么需求,因为开发成本低啊!为什么今日头条的这个屏幕适配方案现在能这么火,因为他的开发成本是目前所有屏幕适配方案中最低的啊!

DPI的意义谁又不懂呢?难道就你懂,今日头条这种大公司的程序员不懂这个道理吗?今日头条这么大的公司难道不想把每个机型每个版本的设备都适配完美,让自己的App体验更好,哪怕付出更大的成本,有些时候想象是美好的,但是这个投入的成本,谁又能承担呢,连今日头条这么大的公司,这么雄厚的资本都没选择投入更大的成本,对每个机型进行更精细化的适配,难道市面上的中小型公司又有这个能力投入这么大的成本吗?

鱼和熊掌不可兼得,DPI的意义在Google的设计理念中是完全正确的,但不是所有公司都能承受这个成本,想必今日头条的程序员,也是因为今日头条App的用户量足够多,机型分布足够广,也是被屏幕适配这个问题折磨的不要不要的,才想出这么个不这么完美但是却很有效的方案

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。