dpi
:屏幕密度,屏幕上每英寸上有多少像素点.屏幕对角线上的像素点总数除以屏幕对角线长度得到.dip
:也就是最常用的dp
单位,屏幕上每英寸有160个点,每个点如果代表1像素,那么1dp就等于1像素.density
:每1英寸像素点除160,也就是每英寸有160个点,每个点能覆盖多少个像素.AdaptScreenUtils
它是如何做的适配Activity
中的getResources()
方法,如下:@Override
public Resources getResources() {
// 这里是以高度为基准来适配的
return AdaptScreenUtils.adaptHeight(super.getResources(), "UI高度像素值");
}
public final class AdaptScreenUtils {
public static Resources adaptHeight(final Resources resources, final int designHeight) {
// designHeight代表UI设计稿中的高度像素值
return adaptHeight(resources, designHeight, false);
}
public static Resources adaptHeight(final Resources resources, final int designHeight, final boolean includeNavBar) {
// 获取屏幕高度像素值
float screenHeight = (resources.getDisplayMetrics().heightPixels + (includeNavBar ? getNavBarHeight(resources) : 0)) * 72f;
// 以屏幕高度像素值除以设计稿中高度像素值,传入applyDisplayMetrics()方法中
float newXdpi = screenHeight / designHeight;
applyDisplayMetrics(resources, newXdpi);
return resources;
}
private static void applyDisplayMetrics(final Resources resources, final float newXdpi) {
// 将上面得到值赋值给DisplayMetrics中的xdpi变量
resources.getDisplayMetrics().xdpi = newXdpi;
Utils.getApp().getResources().getDisplayMetrics().xdpi = newXdpi;
applyOtherDisplayMetrics(resources, newXdpi);
}
// 该方法是通过反射为将resources对象中的xdpi变量改为newXdpi值.
private static void applyOtherDisplayMetrics(final Resources resources, final float newXdpi) {
if (sMetricsFields == null) {
sMetricsFields = new ArrayList<>();
Class resCls = resources.getClass();
Field[] declaredFields = resCls.getDeclaredFields();
while (declaredFields != null && declaredFields.length > 0) {
for (Field field : declaredFields) {
if (field.getType().isAssignableFrom(DisplayMetrics.class)) {
field.setAccessible(true);
DisplayMetrics tmpDm = getMetricsFromField(resources, field);
if (tmpDm != null) {
sMetricsFields.add(field);
tmpDm.xdpi = newXdpi;
}
}
}
// 包括resources父类对象中的xdpi值都要改为newXdpi值
resCls = resCls.getSuperclass();
if (resCls != null) {
declaredFields = resCls.getDeclaredFields();
} else {
break;
}
}
} else {
applyMetricsFields(resources, newXdpi);
}
}
}
xDpi
在哪儿用的上?
public class TypedValue {
public static float applyDimension(int unit, float value,DisplayMetrics metrics){
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
// 假如使用的是pt作为单位,xdpi为屏幕像素比设计稿像素,再乘以当前value值,最终的结果就是value值在屏幕中所占像素值.后面的我不太懂0.0.
// 使用pt作为单位可以避开dp单位,这样对原有的项目影响最小.
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}
}
对于TextView
中文字大小,建议使用sp
作为单位,这样文字大小可以自动适配.然后千万不要写死TextView
尺寸大小,不然很容易出现文字比TextView
尺寸还大导致显示不全的现象.建议使用wrap_content
.