今日頭條適配方案
android中的dp在渲染前會將dp轉爲px,計算公式:
-
px = density * dp;
-
density = dpi / 160;
-
px = dp * (dpi / 160);
而dpi是根據屏幕真實的分辨率和尺寸來計算的,每個設備都可能不一樣的。
通常情況下,一部手機的分辨率是寬x高,屏幕大小是以寸爲單位,那麼三者的關係是:
從dp和px的轉換公式 :px = dp * density
可以看出,如果設計圖寬爲360dp,想要保證在所有設備計算得出的px值都正好是屏幕寬度的話,我們只能修改 density 的值。
原理:
當前設備屏幕總寬度(單位爲像素)/ 設計圖總寬度(單位爲 dp) = density
所以此時我們的scaledDensity
應該這樣計算:scaledDensity = 人爲修改的density * (系統的ScaledDensity / 系統的Density)
// 系統的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;
}
優點
-
使用成本非常低,操作非常簡單,使用該方案後在頁面佈局時不需要額外的代碼和操作,這點可以說完虐其他屏幕適配方案
-
侵入性非常低,該方案和項目完全解耦,在項目佈局時不會依賴哪怕一行該方案的代碼,而且使用的還是 Android 官方的 API,意味着當你遇到什麼問題無法解決,想切換爲其他屏幕適配方案時,基本不需要更改之前的代碼,整個切換過程幾乎在瞬間完成,會少很多麻煩,節約很多時間,試錯成本接近於 0
-
可適配三方庫的控件和系統的控件(不止是 Activity 和 Fragment,Dialog、Toast 等所有系統控件都可以適配),由於修改的 density 在整個項目中是全局的,所以只要一次修改,項目中的所有地方都會受益
-
不會有任何性能的損耗
缺點
當某個系統控件或三方庫控件的設計圖尺寸和和我們項目自身的設計圖尺寸差距非常大時,這個問題就越嚴重
smallestWidth 限定符適配方案
或者叫sw限定符適配。指的是Android會識別屏幕可用高度和寬度的最小尺寸的dp值(其實就是手機的寬度值),然後根據識別到的結果去資源文件中尋找對應限定符的文件夾下的資源文件。
smallestWidth限定符適配和寬高限定符適配最大的區別在於,前者有很好的容錯機制,如果沒有value-sw360dp文件夾,系統會向下尋找,比如離360dp最近的只有value-sw350dp,那麼Android就會選擇value-sw350dp文件夾下面的資源文件。
apk可能會增大300kb-800kb左右,
生成diemns文件的項目地址
https://github.com/ladingwu/dimens_sw
Q: 該適配方案怎麼用?
A:點擊進入上文的github項目,下載到本地,然後運行該Java工程,會在本地根目錄下生成相應的文件,如果需要生成更多尺寸,在DimenTypes 文件中填寫你需要的尺寸即可。
Q: 是否有推薦的尺寸?
A 300,320,360,411,450,這幾個尺寸是比較必要的,然後在其中插入一些其他的尺寸即可,如果不放心,可以在300-450之間,以10爲步長生成十幾個文件。
參考文檔: