android适配方案简介

常见适配

  • dimen 基于px

宽和高都经过百分比的计算得到对应的值,通过手机分辨率进行适配,个人看来存在的问题是:

第一,Android不同分辨率的手机实在太多了,可能你说主流就可以,的确小公司主流就可以,淘宝这种App肯定不能只适配主流手机。

第二,控件在设计图上显示的大小以及控件之间的间隙在小分辨率和大分辨率手机上天壤之别,你会发现大屏幕手机上控件超级大。可能你会觉得正常,毕竟分辨率不同。但实际效果大的有些夸张。

第三,设计图(比如360640)上的内容占据屏幕的2/3,按照这种适配,特长手机(29601440 S8)上的内容也会占据2/3,这肯定不合理,控件之间的间隙会特别大,一看就不符合设计效果,手机长,内容占据低于2/3才正常,比如可能占据1/3.第四,占据资源大:好几百KB,甚至多达1M或跟多。

  • dimen 基于dp

这种适配依据的是最小宽度限定符。个人看来存在的问题是:

第一,Android 私人订制的原因,宽度方面参差不齐,不可能适配所有的手机。

第二,sp和dp值有些值不全(这个应该是可以解决的),姑且算是一个小问题。

第三,项目中增加了N个文件夹,上拉下拉查看文件非常不方便:想看string或者color资源文件需要拉很多再能到达。

详解dimens-px 适配

原理:根据市面上手机分辨率的占比分析,我们把1280和720设定为一个基准,然后其他分辨率根据这个基准做适配。

基准的意思(比如320*480的分辨率为基准)是:

  • 宽为320,将任何分辨率的宽度分为320份,取值为x1到x320

  • 长为480,将任何分辨率的高度分为480份,取值为y1到y480

例如对于800*480的宽度480:

<?xml version="1.0" encoding="utf-8"?>
<resources><dimen name="x1">1.5/dimen>
<dimen name="x2">3.0px</dimen>
<dimen name="x3">4.5</dimen>
<dimen name="x4">6.0px</dimen>
<dimen name="x5">7.5px</dimen>

可以看到x1 = 480 / 基准 = 480 / 320 = 1.5 ;它的意思就是同样的1px,在320/480分辨率的手机上是1px,在480/800的分辨率的手机上就是1*1.5px,px会根据我们指定的不同values文件夹自动适配为合适的大小。

推荐适配

  • 现状

UI设计图是按屏幕宽度为360dp来设计的,那么在上述设备上,屏幕宽度其实为1080/(440/160)=392.7dp,也就是屏幕是比设计图要宽的。这种情况下, 即使使用dp也是无法在不同设备上显示为同样效果的。 同时还存在部分设备屏幕宽度不足360dp,这时就会导致按360dp宽度来开发实际显示不全。加上16:9、4:3甚至其他宽高比层出不穷,宽高比不同,显示完全一致就不可能了,不信你去看看pixel 2的density就明白了。

  • 解决方案

通常下,我们只需要以宽或高一个维度去适配,比如我们Feed是上下滑动的,只需要保证在所有设备中宽的维度上显示一致即可,再比如一个不支持上下滑动的页面,那么需要保证在高这个维度上都显示一致,尤其不能存在某些设备上显示不全的情况。

  • 实质

支持以宽或者高一个维度去适配,保持该维度上和设计图一致;
支持dp和sp单位,控制迁移成本到最小。

  • 具体代码

px = dp * density dp是360dp,想要px正好是屏幕宽度的话,只能修改density。

/**
     * 适配:修改设备密度
     */
    private static float sNoncompatDensity;
    private static float sNoncompatScaledDensity;

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

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

    }
DisplayUtil.setCustomDensity(this, getApplication());

参考文章:https://pan.baidu.com/share/init?surl=crbwwI

猜你喜欢

转载自blog.csdn.net/liangtianmeng/article/details/82316254