先放三張自己做code review的ppt
從上面的圖片上已經(jīng)知道了大概。
由于Android碎片化嚴(yán)重,雖然Android官方提供了dp單位來適配,解決了大部分的問題汰现。但是還是有細(xì)節(jié)問題,這就是今天的內(nèi)容叔壤。
存在什么問題呢瞎饲?
假設(shè)我們UI設(shè)計(jì)圖是按屏幕寬度為360dp來設(shè)計(jì)的,那么在上述設(shè)備上炼绘,屏幕寬度其實(shí)為1080/(440/160)=392.7dp嗅战,也就是屏幕是比設(shè)計(jì)圖要寬的。這種情況下俺亮, 即使使用dp也是無法在不同設(shè)備上顯示為同樣效果的驮捍。 同時(shí)還存在部分設(shè)備屏幕寬度不足360dp,這時(shí)就會(huì)導(dǎo)致按360dp寬度來開發(fā)實(shí)際顯示不全的情況脚曾。
而且上述屏幕尺寸东且、分辨率和像素密度的關(guān)系,很多設(shè)備并沒有按此規(guī)則來實(shí)現(xiàn)本讥, 因此dpi的值非常亂珊泳,沒有規(guī)律可循,從而導(dǎo)致使用dp適配效果差強(qiáng)人意拷沸。
解決方法
從上圖中可以看出色查,android最終的尺寸單位還是轉(zhuǎn)為px進(jìn)行布局的。px = density * dp;
既然dpi(屏幕像素密度)不能改變撞芍,dp也是在代碼中寫死秧了。那只能改變density了。
通過閱讀源碼序无,我們可以得知验毡,density 是 DisplayMetrics 中的成員變量衡创,而 DisplayMetrics 實(shí)例通過 Resources#getDisplayMetrics 可以獲得,而Resouces通過Activity或者Application的Context獲得晶通。
先來熟悉下 DisplayMetrics 中和適配相關(guān)的幾個(gè)變量:
1.DisplayMetrics#density 就是上述的density
2.DisplayMetrics#densityDpi 就是上述的dpi
3.DisplayMetrics#scaledDensity 字體的縮放因子钧汹,正常情況下和density相等,但是調(diào)節(jié)系統(tǒng)字體大小后會(huì)改變這個(gè)值
/**
* 設(shè)置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中調(diào)用下录择,即可解決分析的問題,有沒有調(diào)用私有api碗降,簡單隘竭,不需要改動(dòng)之前代碼。
還是不錯(cuò)的讼渊。