屏幕適配好幾種捆昏,目前主流且成本最低的還是修改系統(tǒng)density的方案邓线。
概念
- 像素:屏幕的最小單位淌友,單位為px煌恢。
- 分辨率:整個(gè)屏幕一共有多少個(gè)點(diǎn),也就是像素震庭。例如分辨率1920*1080就是指屏幕橫向和縱向分別是1920和1080個(gè)像素組成瑰抵。
- 像素密度(dpi):每英寸中的像素?cái)?shù)。假如設(shè)備分辨率為320*240器联,屏幕長(zhǎng)2英寸寬1.5英寸二汛,dpi=320/2 = 240/1.5 =160。對(duì)應(yīng)于DisplayMetrics類中屬性densityDpi的值拨拓。
- 屏幕密度(density):每平方英寸中的像素?cái)?shù)肴颊,density = dpi / 160 ,對(duì)應(yīng)于DisplayMetrics類中屬性density的值渣磷,可用于px與px與dip的互相轉(zhuǎn)換 :dp = px / density婿着。
常見(jiàn)設(shè)備的dp、px幸海、density的關(guān)系
分辨率 | density | dpi | |
---|---|---|---|
hdpi | 480 * 800 | 1.5 | 240 |
xhdpi | 720 * 1280 | 2.0 | 320 |
xxhdpi | 1080 * 1920 | 3.0 | 480 |
原理
美工給我們?cè)O(shè)計(jì)圖大部分公司的給的是px單位的祟身,并且只給一套UI圖,我們需要適配屏幕分辨率各種各樣的手機(jī)物独,這里推薦一個(gè)UI和開(kāi)發(fā)方便溝通平臺(tái):https://lanhuapp.com/袜硫,UI給我們的設(shè)計(jì)圖是一個(gè)固定值,我們需要以屏幕的寬最為參考挡篓,計(jì)算一個(gè)比例婉陷,然后將計(jì)算得到的density設(shè)置給Activity,注意在setContentView之前設(shè)置官研。
實(shí)現(xiàn)
我們將修改Density的方法抽成工具類秽澳,需要注意的是當(dāng)我們?cè)谙到y(tǒng)中修改系統(tǒng)字體大小后,系統(tǒng)的scaledDensity會(huì)發(fā)生改變戏羽,因此我們需要監(jiān)聽(tīng)用戶修改系統(tǒng)字體担神,然后重新設(shè)置scaledDensity,代碼很簡(jiǎn)單始花,直接上工具類妄讯。
public class EDensityUtils {
// private static final float WIDTH = 480;//參考設(shè)備的寬,單位是dp DPI:640
// private static final float WIDTH = 640;//參考設(shè)備的寬酷宵,單位是dp DPI:480
// private static final float WIDTH = 960;//參考設(shè)備的寬亥贸,單位是dp DPI:320
private static final float WIDTH = 1920;//參考設(shè)備的寬,單位是dp DPI:160時(shí)
private static float appDensity;//表示屏幕密度
private static float appScaleDensity; //字體縮放比例浇垦,默認(rèn)appDensity
private EDensityUtils() {
throw new UnsupportedOperationException("you can't instantiate EDensityUtils...");
}
public static void setDensity(final Application application, Activity activity){
//獲取當(dāng)前app的屏幕顯示信息
DisplayMetrics displayMetrics = application.getResources().getDisplayMetrics();
if (appDensity == 0){
//初始化賦值操作
appDensity = displayMetrics.density;
appScaleDensity = displayMetrics.scaledDensity;
//添加字體變化監(jiān)聽(tīng)回調(diào)
application.registerComponentCallbacks(new ComponentCallbacks() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
//字體發(fā)生更改炕置,重新對(duì)scaleDensity進(jìn)行賦值
if (newConfig != null && newConfig.fontScale > 0){
appScaleDensity = application.getResources().getDisplayMetrics().scaledDensity;
}
}
@Override
public void onLowMemory() {
}
});
}
//計(jì)算目標(biāo)值density, scaleDensity, densityDpi
float targetDensity = displayMetrics.widthPixels / WIDTH; // 1920 / 1920 = 1.0
float targetScaleDensity = targetDensity * (appScaleDensity / appDensity);
int targetDensityDpi = (int) (targetDensity * 160);
//替換Activity的density, scaleDensity, densityDpi
DisplayMetrics dm = activity.getResources().getDisplayMetrics();
dm.density = targetDensity;
dm.scaledDensity = targetScaleDensity;
dm.densityDpi = targetDensityDpi;
}
}
使用也十分簡(jiǎn)單,只需要在BaseActivity的onCreate方法中調(diào)用setDensity方法即可,注意的是應(yīng)該在setContentView之前設(shè)置
public class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EDensityUtils.setDensity(getApplication(),this);
}
}