Android适配新方案

Android开发适配是一个问题,各种尺寸与分辨率的手机出现在我们眼前,谷歌也没给出一个令人满意的适配方案,所以只能不断寻求好用的适配方案,最近发现今日头条的一种适配方案还是挺实用的。

要做好屏幕适配,先得知道dp与px的关系,以及屏幕尺寸、分辨率、像素密度三者之间个关系。

  • px = density * dp;
  • density = dpi / 160;
  • px = dp * (dpi / 160);

拿一部尺寸5.0,分辨率为1920 * 1080的手机为例

《Android适配新方案》 1.png

《Android适配新方案》 2.png

由图1公式可以算出该手机的像素密度约为440dpi,尺寸是指手机屏幕对角线的物理长度,像素密度是指没英尺有多少个像素点,就好比是糖水的浓度一样。

以宽作为维度,由这几条公式可以发现,dp并不是一个具体的物理长度单位,1dp不知道有多长或者有多少个像素点,总而言之,320dp、321dp、400dp….等都有可能是某一部手机的宽度。这就说明dp很多时候是个很糟糕的适配单位,宽度160dp的view有可能是屏幕的一般,有可能是屏幕的2/5这样子,适配效果就比较糟糕了,这时候可能就要用到控件权重这些手段进行适配,而不是写死160dp了,这种方式就比较麻烦了。

所以,探索新方案可以从这条公式出发: px = density * dp,我们改变density 的值,dp设为一个一个固定值340,那么每部手机都成立 px = 340dp * density ,也就是说,只要我们改变了该手机的density 值,那么该手机的宽就相当于360dp了,这样在宽的维度上就能很好的适配view的显示效果了。直接上效果图:

《Android适配新方案》 预览图.png
《Android适配新方案》 真机效果.png

具体修改方法:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //设置在setContentView()方法上面
    setCustomDensity(MainActivity.this, getApplication());
    setContentView(R.layout.activity_main);


}

private static float sNoncompatDensity;
private static float sNoncompatScaledDensity;

private static void setCustomDensity(@NonNull Activity activity, @NonNull final Application application) {
    final 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() {

            }
        });
    }

    final float targetDensity = (float) (appDisplayMetrics.widthPixels / 340.0);
    final float targetScaledDensity = targetDensity * (sNoncompatScaledDensity / sNoncompatDensity);
    final int targetDensityDpi = (int) (160 * targetDensity);

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

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

通过debug可以对比修改前与修改后的DisplayMetrics

《Android适配新方案》 修改前.png

《Android适配新方案》 修改后.png

需要注意的是该方法设置在setContentView()方法上面,不然不会起作用,以及需要监听配置的改变,不然修改了系统字体的大小之后,切换回来,字体大小不会变化。

如果发现有什么错误或改进欢迎指出哦,或者发现有更好的适配思路或者方案可以一起研究,如果喜欢可以点点爱心哦。

    原文作者:amazingokc
    原文地址: https://www.jianshu.com/p/8642a3b3f3fc
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞