谈一谈今日头条屏幕适配方案实现"增量"适配

浅谈适配都有那些

  • 宽高限定符适配
  • 鸿洋的 AndroidAutoLayout
  • 今日头条的适配方案

(一)什么是宽高限定符适配

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

这种,在资源文件下生成不同分辨率的资源文件,然后在布局文件中引用对应的 dimens

缺点:对应不同分辨率有着不同的资源文件的弊端,相比也清楚,每出一款不同分辨率的机型都需要创建一个单独的资源,其实是很难涵盖所有机型的

(二) 鸿洋的 AndroidAutoLayout

AndroidAutoLayout地址
这是一款百分比屏幕适配框架,按道理这是一款真正的适配屏幕的的框架
但是,这框架却不适用于现在了,因为这款百分比布局的框架是建立在16 :9的屏幕的不变的前提下
而当下新时代全面屏横行,AndroidAutoLayout已经水土不服了,在不是16 :9的屏幕下View会严重变形

所以这种百分比的适配方案已经要退出历史舞台

(三)今日头条的适配方案

要说今日头条的适配就要说一下dp,Android推荐使用dp作为尺寸单位来适配UI
android中的dp在渲染前会将dp转为px,计算公式:

px = density * dp;
density = dpi / 160;
px = dp * (dpi / 160);

而dpi是根据屏幕真实的分辨率和尺寸来计算的,每个设备都可能不一样的。

(1)dp 直接适配

  • 那么什么是dp?

dp指的是设备独立像素,以dp为尺寸单位的控件,在不同分辨率和尺寸的手机上代表了不同的真实像素,比如在分辨率较低的手机中,可能1dp=1px,而在分辨率较高的手机中,可能1dp=2px,这样的话,一个96*96dp的控件,在不同的手机中就能表现出差不多的大小了。

  • 那么这个dp是如何计算的呢?

我们都知道一个公式:从dp和px的转换公式 :px = dp * density 系统都是通过这个来判断px和dp的数学关系,

可以看出,如果设计图宽为360dp,想要保证在所有设备计算得出的px值都正好是屏幕宽度的话,我们只能修改 density 的值。

通过阅读源码,我们可以得知,density 是 DisplayMetrics 中的成员变量,而 DisplayMetrics 实例通过 Resources#getDisplayMetrics 可以获得,而Resouces通过Activity或者Application的Context获得。

例:

getResources().getDisplayMetrics().density * dp

先来熟悉下 DisplayMetrics 中和适配相关的几个变量:

  • DisplayMetrics#density 就是上述的density

  • DisplayMetrics#densityDpi 就是上述的dpi

  • DisplayMetrics#scaledDensity 字体的缩放因子,正常情况下和density相等,但是调节系统字体大小后会改变这个值

  • 今日头条的适配方案

下面假设设计图宽度是360dp,以宽维度来适配。

那么适配后的 density = 设备真实宽(单位px) / 360,接下来只需要把我们计算好的 density 在系统中修改下即可,代码实现如下:

 class ScreenAdaptUtil {
     companion object {
         fun setCustomDensity(activity:Activity,application: Application){
             val applicationMetrics = application.resources.displayMetrics
              //真是屏幕宽度/设计图宽(360dp)换算成当前设备的targetDensity
             var targetDensity:Float = (applicationMetrics.widthPixels/360).toFloat()
             var targetDensityDpi = 160*targetDensity

            //因为dp的转换公式px = density * dp,我们根据屏幕修改了density也就达到了我们适配的目的
             applicationMetrics.density = targetDensity
            //正常情情况下字体scaledDensity是和density是一致的,但是会因为修改字体而修改scaledDensity,为了保持适配我们使用targetDensity避免这个问题
             applicationMetrics.scaledDensity = targetDensity
             applicationMetrics.densityDpi = targetDensityDpi.toInt()

             val activityMetrics = activity.resources.displayMetrics
             activityMetrics.density = targetDensity
             activityMetrics.scaledDensity = targetDensity
             activityMetrics.densityDpi = targetDensityDpi.toInt()
         }
     }
}

在activity中应用

 ScreenAdaptUtil.setCustomDensity(this,application)

这是一个简单的今日头条适配方案的的简单代码

(三) 基于今日头条的适配方案的AndroidAutoSize

AndroidAutoSize地址
具体使用参考AndroidAutoSize使用说明,这里不做特别的说明

AndroidAutoSize或者说今日头条真的没有问题吗?

其实还是在实践中发现了问题

因为是修改了是常量,所以会 导致APP全局都会生效所以会引起:

  • 今日头条适配方案会影响一些三方库和系统控件
  • 老项目的某些页面之前使用了 dp 进行布局,并且 AndroidAutoSize 可能这些页面会有一些不良影响

(三) 使用AndroidAutoSize副单位做增量适配

  • 在Android开发中,dp、sp两个主单位,pt、in、mm三个冷门副单位,AndroidAutoSize支持副单位,如果使用副单位,可以规避系统控件或三方库控件使用的不良影响
  • 如果使用副单位,则可以直接填写像素尺寸,不需要再将像素转化为 dp

使用副单位的预览布局问题

布局时的实时预览在开发阶段是一个很重要的环节,很多情况下 Android Studio 提供的默认预览设备并不能完全展示我们的设计图,所以我们就需要自己创建模拟设备,我们这里以mm 这种单位的模拟设备创建方法


创建预览设备.png

如果您在 layout 文件中使用 mm 作为单位进行布局 (需要通过 AutoSizeConfig.getInstance().getUnitsManager().setSupportSubunits(Subunits.MM); 打开对单位 mm 的支持),则可以根据公式 (sqrt(纵向分辨率2+横向分辨率2))/25.4 求出屏幕尺寸,然后创建模拟设备 (只用填写屏幕尺寸和分辨率)

我们的设计图是以苹果设计为主的 也就是750*1334


创建预览设备.png

选择当前副单位的设备预览


创建预览设备.png

(每天学习一点点.每天进步一点点,分享不宜路过点个赞呀,喜欢的点个关注后续更新不断)

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

推荐阅读更多精彩内容