Android对不同DPI的dimen选择优先级问题

问题描述

笔者最近发现这么一个问题,如果仅对values-ldpi和values-xxhdpi下的dimen进行设定,那么hdpi下的手机进行将会如何选择呢?

问题解决

笔者通过查找native层的源代码ResourceType.cpp中的isBetterThan()方法得到了确切的答案。先看看源码对这个屏幕密度适配做了怎样的处理。

bool ResTable_config::isBetterThan(const ResTable_config& o,        const ResTable_config* requested) const {        ..........       if (screenType || o.screenType) {            if (density != o.density) {                // Use the system default density (DENSITY_MEDIUM, 160dpi) if none specified.                const int thisDensity = density ? density : int(ResTable_config::DENSITY_MEDIUM);                const int otherDensity = o.density ? o.density : int(ResTable_config::DENSITY_MEDIUM);                // We always prefer DENSITY_ANY over scaling a density bucket.                if (thisDensity == ResTable_config::DENSITY_ANY) {                    return true;                } else if (otherDensity == ResTable_config::DENSITY_ANY) {                    return false;                }                int requestedDensity = requested->density;                if (requested->density == 0 ||                        requested->density == ResTable_config::DENSITY_ANY) {                    requestedDensity = ResTable_config::DENSITY_MEDIUM;                }                // DENSITY_ANY is now dealt with. We should look to                // pick a density bucket and potentially scale it.                // Any density is potentially useful                // because the system will scale it. Scaling down                // is generally better than scaling up.                int h = thisDensity;                int l = otherDensity;                bool bImBigger = true;                if (l > h) {                    int t = h;                    h = l;                    l = t;                    bImBigger = false;                }                if (requestedDensity >= h) {                    // requested value higher than both l and h, give h                    return bImBigger;                }                if (l >= requestedDensity) {                    // requested value lower than both l and h, give l                    return !bImBigger;                }                // saying that scaling down is 2x better than up                if (((2 * l) - requestedDensity) * h > requestedDensity * requestedDensity) {                    return !bImBigger;                } else {                    return bImBigger;                }            }    .......}

总体来说走的就近原则,选择离当前密度最近的适配值。系统会便遍历整个values下对应的dimen值,选择一个可包含当前屏幕密度的最小区间,如果实在找不到这样的区间,如ldpi和hdpi进行了适配,但是手机是xxhdpi,那么此时就会选择离当前手机屏幕密度最近的端点进行适配,也就是(requestedDensity >= h)或者(l >= requestedDensity—)的情况。如果这样的区间存在,那么就执行 (((2 * l) - requestedDensity) * h > requestedDensity * requestedDensity) 的算法,这里requestedDensity就指的是需要适配手机屏幕密度。这里的l和h为其具体值(单位dpi,如240dpi)与系统默认密度160dpi的比值,也就是系统对dp转化为px的缩放比。

举个例子,就以开篇的那个问题为例,此时l = 0.75, h = 3.0,requestedDensity = 1.5, 那么可以计算得出((2 * l) - requestedDensity) * h < requestedDensity * requestedDensity),返回true,也就是返回了h,也就是xxhdpi的dimen值

从哪里回去此篇代码呢?这个CPP是从GITHUB中直接clone过来的,如果读者需要,只要执行

$git clone https://github.com/android/platform_frameworks_base.git

即可此文件。

更多相关文章

  1. android数据单位dp,px和sp
  2. Android(安卓)Multiple Screens Android(安卓)屏幕适配的一些总
  3. Android(安卓)TextView文字滚动
  4. Android(安卓)图片文字单位 px、dp、sp区别
  5. Android(安卓)density与显示效果总结
  6. Android(安卓)ListView 如何 更改字体颜色,字体类型等参数
  7. Android上dip、dp、px、sp等单位说明
  8. Android(安卓)Android-skin-support 换肤方案 原理讲解
  9. Android短信转发默认不需要转发号码修改方法

随机推荐

  1. 一张图看明白 Android(安卓)Handler 消息
  2. android 面向对象数据库 db40使用demo
  3. android实现页面下方的Tab效果 .
  4. Android(安卓)判断Intent是否存在
  5. 使用android中的handler延迟执行方法
  6. Android学习网站(1)
  7. Android使用科大讯飞实现语音播报、语音
  8. 理解onMeasure
  9. Android(安卓)常用颜色
  10. android动画效果2