Android屏幕碎片化细节优化

先放三张自己做code review的ppt


2.png

1.png

3.png

从上面的图片上已经知道了大概。

由于Android碎片化严重,虽然Android官方提供了dp单位来适配,解决了大部分的问题。但是还是有细节问题,这就是今天的内容。

存在什么问题呢?

假设我们UI设计图是按屏幕宽度为360dp来设计的,那么在上述设备上,屏幕宽度其实为1080/(440/160)=392.7dp,也就是屏幕是比设计图要宽的。这种情况下, 即使使用dp也是无法在不同设备上显示为同样效果的。 同时还存在部分设备屏幕宽度不足360dp,这时就会导致按360dp宽度来开发实际显示不全的情况。

而且上述屏幕尺寸、分辨率和像素密度的关系,很多设备并没有按此规则来实现, 因此dpi的值非常乱,没有规律可循,从而导致使用dp适配效果差强人意。

解决方法

从上图中可以看出,android最终的尺寸单位还是转为px进行布局的。px = density * dp;

既然dpi(屏幕像素密度)不能改变,dp也是在代码中写死。那只能改变density了。

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

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

1.DisplayMetrics#density 就是上述的density

2.DisplayMetrics#densityDpi 就是上述的dpi

3.DisplayMetrics#scaledDensity 字体的缩放因子,正常情况下和density相等,但是调节系统字体大小后会改变这个值
/**
     * 设置activity页面 density
     * @param activity
     * @param application
     */
    public static void setCustomDensity(Activity activity, final Application application){
        final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();

        if(sNoncompatDesity == 0){
            sNoncompatDesity = appDisplayMetrics.density;
            sNoncompatScaledDensity = appDisplayMetrics.scaledDensity;
            application.registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    if(newConfig != null && newConfig.fontScale > 0){
                        sNoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                    }
                }

                @Override
                public void onLowMemory() {

                }
            });
        }
        final float targetDensity = appDisplayMetrics.widthPixels / 360;
        final float targetScaledDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDesity);
        final int targetDensityDpi = (int)(160 * targetDensity);


        appDisplayMetrics.density = targetDensity;
        appDisplayMetrics.scaledDensity = targetScaledDensity;
        appDisplayMetrics.densityDpi = targetDensityDpi;

        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        activityDisplayMetrics.density = targetDensity;
        activityDisplayMetrics.scaledDensity = targetScaledDensity;
        activityDisplayMetrics.densityDpi = targetDensityDpi;
    }

只要在oncreate中调用下,即可解决分析的问题,有没有调用私有api,简单,不需要改动之前代码。

还是不错的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 174,799评论 25 709
  • 1、基础概念 屏幕尺寸 含义:指的屏幕对角线的物理长度,单位一般采用英寸(1英寸≈2.53cm) 目前市面常见的有...
    古都旧城阅读 2,790评论 0 1
  • 任何事情的发生都是有原因的,这是所谓的因果。 如果没有很好的坐姿习惯,不仅会增加近视的可能,还会加大体态不正的可能...
    恩煦阅读 104评论 1 0
  • 知,予以众之望,求而得之,力所及天下人之苦,天下人之所乐,古曰,成大器者“必先苦其心志,劳其筋骨,饿其体肤”,吾曰...
    芝初阅读 302评论 1 7
  • 转眼间时光就已溜走 次第再无桃花开放 在这个孤单寂寞的黄昏 一个举杯与谁共饮 大醉 酒醒 再醉 日子就这样匆匆复匆...
    想飞的鱼521314阅读 170评论 0 0