1. 程式人生 > >今日頭條的安卓適配方案,值得收藏

今日頭條的安卓適配方案,值得收藏

文章連結,之前確實沒有接觸過,我簡單看了一遍,可以說,這也是相對比較完美的方案,我先簡單說一下這個方案的思路,它是通過修改density值,強行把所有不同尺寸解析度的手機的寬度dp值改成一個統一的值,這樣就解決了所有的適配問題。

比如,設計稿寬度是360px,那麼開發這邊就會把目標dp值設為360dp,在不同的裝置中,動態修改density值,從而保證(手機畫素寬度)px/density這個值始終是360dp,這樣的話,就能保證UI在不同的裝置上表現一致了。

這個方案侵入性很低,而且也沒有涉及私有API,應該也是極不錯的方案,我暫時也想不到強行修改density是否會有其他影響,既然有今日頭條的大廠在用,穩定性應當是有保證的。

但是根據我的觀察,這套方案對老專案是不太友好的,因為修改了系統的density值之後,整個佈局的實際尺寸都會發生改變,如果想要在老專案檔案中使用,恐怕整個佈局檔案中的尺寸都可能要重新按照設計稿修改一遍才行。因此,如果你是在維護或者改造老專案,使用這套方案就要三思了。

具體程式碼實現為:

    // 今日頭條的螢幕適配方案
    // 通過修改density值,強行把所有不同尺寸解析度的手機的寬度dp值改成一個統一的值,這樣就解決了所有的適配問題
    // @param activity
    // @param application

    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;
    }