首先,先了解一下几个基本概念:
px:像素点;
dpi:像素密度,每英寸有多少个像素点;对应于DisplayMetrics类中属性densityDpi的值;
dp:可以根据不同的屏幕获得不同的像素数量;当屏幕每英寸有160个像素时,dp与px等价;dp最终都要化为像素数量来衡量大小的,因为只有像素数量最直观;
density:密度(以mdpi(160dpi)为基准,相对标准情况下的像素密度的比例);
density = dpi / 160;
density = px / dp;
通常情况下,一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:
Android开发中,图片素材会根据素材的分辨率大小,放在如下几个文件夹中:
ldpi(120dpi)
mdpi(160dpi)
hdpi(240dpi)
xdpi(320dpi)
xxdpi(480dpi)
xxxdpi(640dpi)
以mdpi(160dpi)为基准,比例关系:0.75:1:1.5:2:3:4。
上述文件夹不是指定具体的分辨率,而是一个范围,如ldpi(value<120dpi),mdpi(120dpi<value<160dpi),以此类推。资源文件加载时,就是根据手机分辨率选择合适的文件夹加载资源。
UI设计图是按屏幕宽度为360dp来设计的,如果需要修改,只能改density。
今日头条的这种适配,只需要在baseActivity中添加一句话即可。
/**
* 适配:修改设备密度
*/
private static float sNoncompatDensity;
private static float sNoncompatScaledDensity;
public static void setCustomDensity(Activity activity) {
final Application application = BaseApplication.getInstance();
DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();
if (sNoncompatDensity == 0) {
sNoncompatDensity = 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() {
}
});
}
float targetDensity = appDisplayMetrics.widthPixels / 360;
// 防止字体变小
float targetScaleDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
int targetDensityDpi = (int) (160 * targetDensity);
appDisplayMetrics.density = targetDensity;
appDisplayMetrics.scaledDensity = targetScaleDensity;
appDisplayMetrics.densityDpi = targetDensityDpi;
DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
activityDisplayMetrics.density = targetDensity;
activityDisplayMetrics.scaledDensity = targetScaleDensity;
activityDisplayMetrics.densityDpi = targetDensityDpi;
}