Android屏幕適配之--通過修改系統(tǒng)的屏幕像素比來實(shí)現(xiàn)屏幕的適配效果
關(guān)于Android中dip,dpi,density,px的詳細(xì)解釋參考簡(jiǎn)書前輩的文章Android開發(fā)中dip,dpi,density,px等詳解
當(dāng)然在下面的代碼中,density代表的是縮放比,densityDpi代表的是像素密度(就是一個(gè)dp中有多少個(gè)px),Android官方中是以160為基準(zhǔn)dpi
做一個(gè)簡(jiǎn)要的說明:在顯示中,實(shí)際都是以像素px為單位來對(duì)控件的大小進(jìn)行指定的,所以數(shù)值在換算的公式是這樣的
實(shí)際顯示的像素值px = 縮放比 * 設(shè)置的dp值
縮放比 = 實(shí)際的dpi / 160(基準(zhǔn)dpi)
代碼不多,先直接把整個(gè)類的代碼貼上來吧
public class DensityUtil {
//屏幕的參考寬度值,單位是dp
private static float STAND_WIDTH = 320;
//系統(tǒng)原來的像素縮放比
private static float appDensity;
private static float appScaleDensity; //字體縮放比
public static void setDensity(final Application application, Activity activity) {
final DisplayMetrics appMetrics = application.getResources().getDisplayMetrics();
if (appDensity == 0) {
//獲取系統(tǒng)本來的像素縮放比和字體縮放比
appDensity = appMetrics.density;
appScaleDensity = appMetrics.scaledDensity;
}
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
//代表字體大小進(jìn)行了更改,需要對(duì)字體縮放比進(jìn)行重新賦值
if(newConfig != null && newConfig.fontScale > 0){
appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;
}
}
@Override
public void onLowMemory() {
}
});
//通過實(shí)際的屏幕大小來計(jì)算新的屏幕像素縮放比
float targetDensity = appMetrics.widthPixels / STAND_WIDTH;
float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
float targetDensityDpi = targetDensity * 160;
//將獲取到的新的縮放比設(shè)置回去
DisplayMetrics actMetrics = activity.getResources().getDisplayMetrics();
actMetrics.density = targetDensity;
actMetrics.densityDpi = (int) targetDensityDpi;
actMetrics.scaledDensity = targetScaleDensity;
}
}
在調(diào)用的時(shí)候,要在目標(biāo)界面Activity的setContentView代碼之前進(jìn)行調(diào)用
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DensityUtil.setDensity(getApplication(),this);
setContentView(R.layout.activity_density);
}
整個(gè)思路就是先拿到整個(gè)屏幕的像素值,然后除以參照的設(shè)計(jì)圖中的設(shè)備寬度dp值,這樣就可以得到一個(gè)目標(biāo)的縮放比,通過這個(gè)縮放比就可以得到字體的縮放比和像素密度,然后在把得到的這幾個(gè)值給設(shè)置回去。
疑問
可能在代碼中會(huì)有這樣的疑問,為什么要先獲取Application的appDensity、appScaleDensity這些參數(shù),經(jīng)過換算后替換成Activity的Density、ScaleDensity,而不是一開始直接獲取Activity的DisplayMetrics,然后從這個(gè)DisplayMetrics中提取Density、ScaleDensity等屬性,然后直接修改呢?
解答
是這樣的,當(dāng)你改了一個(gè)Activity后,整個(gè)app所有的界面都會(huì)發(fā)生變化,比如A activity的density修改后就,bActivity的也相應(yīng)發(fā)生修改,但是application的density并沒有變化,如果還需要再縮放那就是在已經(jīng)縮放一次的基礎(chǔ)上還會(huì)再乘上一個(gè)對(duì)應(yīng)的倍數(shù),所有這里使用app的DisplayMetrics主要是為了確保計(jì)算正確