Android适配新方案

作者: amazingokc | 来源:发表于2018-08-08 15:40 被阅读80次

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

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

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

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

    1.png
    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的显示效果了。直接上效果图:

    预览图.png 真机效果.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

    修改前.png
    修改后.png

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

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

    相关文章

      网友评论

      本文标题:Android适配新方案

      本文链接:https://www.haomeiwen.com/subject/lqatbftx.html