安卓屏幕适配方案(修改像素密度)

原理
px值 = dp值 * metrics.density,这里的density是指的手机的屏幕密度,由系统提供,不同的手机的density可能不同,所以我们不能直接使用系统的density,通过修改density值,强行把所有不同尺寸分辨率的手机的宽度dp值改成一个统一的值,这样就解决了所有的适配问题。

比如,原设备分辨率为1280×800,其像素密度为320dpi,设计稿宽度就是是1280px,那么开发这边就会把目标dp值设为640dp,在不同的设备中,动态修改density值,从而保证(手机像素宽度)px/density这个值始终是640dp,这样的话,就能保证UI在不同的设备上表现一致了。

如果UI设计图是按屏幕宽度为640dp来设计的,那么在1024×600分辨率的设备上,其修改后的像素密度则为(1024/640)*160=256dpi,屏幕宽度经过计算则为1024/(256/160)=640dp,这就和我们呢UI设计图保持一致了,这样就实现了统一设计图,可以在不同分辨率的屏幕上适配了。

实现

public class DisplayUtil {
    private static float sDensity;

    private static float sScaledDensity;

    public static void setCustomDensity(@NonNull Activity activity, @NonNull final  Application application) {
        DisplayMetrics appDisplayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getRealMetrics(appDisplayMetrics);
        if (sDensity == 0) {
            sDensity = appDisplayMetrics.density;
            sScaledDensity = appDisplayMetrics.scaledDensity;
            // 防止系统切换后不起作用
            application.registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    if (newConfig != null && newConfig.fontScale > 0) {
                        sScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                    }
                }

                @Override
                public void onLowMemory() {

                }
            });
        }
        float targetDensity = (float) appDisplayMetrics.widthPixels / (float) 640;

        // 防止字体变小
        float targetScaleDensity = targetDensity * (sScaledDensity / sDensity);
        int targetDensityDpi = (int) (160 * targetDensity);

        appDisplayMetrics.density = targetDensity;
        appDisplayMetrics.scaledDensity = targetScaleDensity;
        appDisplayMetrics.densityDpi = targetDensityDpi;

        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();
        activityDisplayMetrics.density = targetDensity;
        activityDisplayMetrics.scaledDensity = targetScaleDensity;
        activityDisplayMetrics.densityDpi = targetDensityDpi;

    }
}

该实现是基于设计图宽度为640dp进行适配的,假如UI设计图不一致,只需更改对应的值即可。除此之外,我们也可以高度进行适配,只需替换一行代码即可,例如以高度400dpj进行适配,如下

float targetDensity = (float) appDisplayMetrics.heightPixels / (float) 400;

其中需要注意的是,android 4.4(sdk 19)之后,获取屏幕高度需要考虑底部导航栏等decor,getWindowManager().getDefaultDisplay().getMetrics()等传统方法获取的宽高是不正确的,和adb shell wm size可以查询到设备的物理尺寸不一致,应使用getRealMetrics()方法获取屏幕实际的物理尺寸。


只需要在所需的Activity中,或创建一个公共baseActivity的onCreate中调用即可。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        DisplayUtil.setCustomDensity(this, getApplication());
    }
  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值