關於今日頭條適配方案需要注意的
今日頭條:一種極低成本的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物件沒啥問題的