1. 程式人生 > >關於今日頭條適配方案需要注意的

關於今日頭條適配方案需要注意的

今日頭條:一種極低成本的Android螢幕適配方式
https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA

自從看了今日頭條的適配方案,就被這種容易操作,成本低廉的方案所吸引,大廠出品果然都是精品,大廠的開發在鑽研技術上果然不是吹的。
下面說下第一次使用今日頭條的方案,感受:

剛開始看到程式碼,方案理論,確實很好,++是以更改螢幕密度為核心++,直接把程式碼全部複製下來,放到測試專案中試用今日頭條的方法程式碼

// 系統的Density
 private static float sNoncompatDensity;
 // 系統的ScaledDensity
 private static float sNoncompatScaledDensity;

 public static void setCustomDensity(Activity activity, Application application) {
        DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
        if (sNoncompatDensity == 0) {
            sNoncompatDensity = displayMetrics.density;
            sNoncompatScaledDensity = displayMetrics.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() {

                }
            });
        }
        // 此處以360dp的設計圖作為例子
        float targetDensity=displayMetrics.widthPixels/360;
        float targetScaledDensity=targetDensity*(sNoncompatScaledDensity/sNoncompatDensity);
        int targetDensityDpi= (int) (160 * targetDensity);
        displayMetrics.density = targetDensity;
        displayMetrics.scaledDensity = targetScaledDensity;
        displayMetrics.densityDpi = targetDensityDpi;

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


以上是今日頭條的程式碼;
看到方法的引數和裡面的內容,我就在想為啥同時使用Activity和Application

setCustomDensity(Activity activity, Application application)

其實可以直接使用Application,不必使用Activity啊,為啥要用兩個呢?

然後我就試著只使用Application,拋棄了activity這個引數。

因為這樣不必每一個activity中都要呼叫這個方法了,直接繼承Application,寫在裡面就好了,想想的很美好的樣子

上手開始run()程式碼;

發現方案並沒有起作用,這讓我百思不得其解,然後又重新回到了今日頭條方案上,通過各種查資料發現:

Application中只能獲取螢幕的density,scaledDensity,densityDpi,並不能修改,或者說修改了並不生效。

那好吧,今日頭條的方法果然必須是這樣的,沒有多餘,沒有缺少,果然牛逼
然後我就封裝了一個activity類,測試使用繼承這個類,不必在每個activity中都呼叫一次這樣的方法了。

然後我開始run()程式碼,果然很牛逼第一個手機試驗成功,緊接著把手上的測試機全部試驗一下,果然很完美,正在我開心的時候,測試機上收到其他APP的推送訊息,我點了一下,調整到其他APP,然後我看完,回來準備接著享受這種低成本的適配方案時,發現剛剛適配的方案失效了,what?這是什麼原因?

請注意:我剛剛是從適配的的demo跳轉到了其他的APP,然後又回到了demo

通過多次嘗試,試驗發現適配方法只在呼叫佈局之前更改了該activity的密度,更改完並不是一直更改,而是在onResume()後使用了系統的密度,而我沒有在onResume()方法中新增所以導致了這個情況。

原來,在activity中除了要新增在onCreate中佈局建立之前,還要在onResume()方法中新增一下

這些調整完,我緊接著想到了,彈出對話方塊,以及Toast等等這些,因為彈出對話方塊需要適配,Toast並不需要適配,但是我調整了字型大小,會不會影響到Toast;帶著這些疑問,我就又開始探索了;

發現在使用Application的物件呼叫時Toast的字型大小正常,而彈出框的size就不行了不適配了,原因也很簡單,上述說的,只在activity中適配了

使用activity的物件呼叫Toast時,字型大小發生了不適配,而彈出框就正常

由此發現Toast不能再activity中物件使用,不然會影響字型的,所以我直接封裝了一個Toast使用Application的物件。對於彈出對話方塊,其實一般不怎麼使用Application,只要不使用Application物件沒啥問題的。

差不多到這,基本上沒啥大問題了,專案中基本上都可以通用了。

最後:

1.Application中只能獲取螢幕的density,scaledDensity,densityDpi,並不能修改,或者說修改了並不生效,需要在activity呼叫

2.在activity中除了要新增在onCreate中佈局建立之前,還要在onResume()方法中新增一下

3.由此發現Toast不能再activity中物件使用,不然會影響字型的,所以我直接封裝了一個Toast使用Application的物件。

4.對於彈出對話方塊,其實一般不怎麼使用Application,只要不使用Application物件沒啥問題的