1. <td id="meph7"><ruby id="meph7"></ruby></td>

      Android今日頭條UI適配完善版

      2018-12-24

      前言


      眾所周知 android的碎片化一直困擾著開發者,我們要花很多的時間去做UI適配的工作。主流的適配方案有兩種 1、今日頭條適配 2、smallestWidth適配。具體的實現點擊上述連接查看。


      這里主要講的是今日頭條的適配方案。他的邏輯很簡單,就是更具設計圖稿的寬度去動態的修改android運行設備DisplayMetrics的density、scaledDensity、densityDpi。但是今日頭條只是貼出了示例代碼。運行到正常開發的時候會遇到UI布局錯亂的問題。主要是因為app在運行過程屏幕旋轉、重力感應、切換字體等因素導致onConfigurationChanged 改變導致的 DisplayMetrics的值被恢復。故在此基礎上做了修改保證運行中的穩定性



      原理


      通過閱讀源碼,我們可以得知,density 是 DisplayMetrics 中的成員變量,而 DisplayMetrics 實例通過 Resources#getDisplayMetrics 可以獲得,而Resources通過Activity


      或者Application的Context獲得。我們只需要包裝Resources對象,重寫其getDisplayMetrics方法,修改其原始值


       package com.xcheng.view.autosize;
      import android.content.res.Resources;
      import android.util.DisplayMetrics;
      /**
       * 今日頭條的適配方案
       */
      public class ResourcesWrapper extends Resources {
          private final AutoSize autoSize;
          private float targetDensity;
          private float targetScaledDensity;
          private int targetDensityDpi;
          public ResourcesWrapper(Resources resources, AutoSize autoSize) {
              super(resources.getAssets(), resources.getDisplayMetrics(), resources.getConfiguration());
              this.autoSize = autoSize;
          }
          @Override
          public DisplayMetrics getDisplayMetrics() {
              DisplayMetrics displayMetrics = super.getDisplayMetrics();
              initValue(displayMetrics);
              autoSize(displayMetrics);
              return displayMetrics;
          }
          private void initValue(DisplayMetrics displayMetrics) {
              if (targetDensity == 0) {
                  float nonCompatDensity = displayMetrics.density;
                  float nonCompatScaledDensity = displayMetrics.scaledDensity;
                  float designSizeInDp = autoSize.designSizeInDp;
                  if (designSizeInDp > 0) {
                      targetDensity = displayMetrics.widthPixels / designSizeInDp;
                  } else {
                      targetDensity = displayMetrics.heightPixels / -designSizeInDp;
                  }
                  targetScaledDensity = targetDensity * (nonCompatScaledDensity / nonCompatDensity);
                  targetDensityDpi = (int) (160 * targetDensity);
              }
          }
          private void autoSize(DisplayMetrics displayMetrics) {
              displayMetrics.density = targetDensity;
              displayMetrics.densityDpi = targetDensityDpi;
              if (autoSize.isSupportSp) {
                  displayMetrics.scaledDensity = targetScaledDensity;
              }
          }
      }


      AutoSize源碼


      package com.xcheng.view.autosize;
      /**
       * 創建時間:2018/11/12
       * 編寫人: chengxin
       * 功能描述:適配實體類
       */
      public class AutoSize {
          /**
           * 默認的設計尺寸
           * >0 設置寬度
           * <0 設置高度
           */
          public final float designSizeInDp;
          public final boolean isSupportSp;
          /**
           * @param designSizeInDp 設計寬度貨高度
           * @param isSupportSp    是否支持sp
           */
          public AutoSize(float designSizeInDp, boolean isSupportSp) {
              if (designSizeInDp == 0) {
                  throw new IllegalArgumentException("designSizeInDp==0");
              }
              this.designSizeInDp = designSizeInDp;
              this.isSupportSp = isSupportSp;
          }
      }
      在Activity基類中重寫getResources方法
      @Override
      public Resources getResources() {
          if (mResources == null) {
              final AutoSize autoSize = getAutoSize();
              if (autoSize != null) {
                  mResources = new ResourcesWrapper(super.getResources(), autoSize);
              }
          }
          return mResources != null ? mResources : super.getResources();
      }
      /**
       * 子類可重寫適配
       **/
      @Nullable
      protected AutoSize getAutoSize() {
          return EasyView.AUTOSIZE;
      }

      子類activiy根據需要重寫getAutoSize即可,如:

      返回null表示不適配


      @Nullable
      @Override
      protected AutoSize getAutoSize() {
          return new AutoSize(360/*設計的寬度dp*/, true);
      }


      核心代碼只有這么多,開發者根據需要提取即可。


      tips:


      1、該實現核心思想是通過攔截Resources#getDisplayMetrics()方法,讀者可根據其原理自動擴展支持 PT、IN、MM。

      2、該適配思想最大的優點是穩定性,不會隨著onConfigurationChanged導致其值被恢復為原始值,因為每次調用Resources#getDisplayMetrics()都會重新賦值適配(僅為簡單的


      賦值,不會影響運行效率)。


      github地址:


      https://github.com/xchengDroid/EasyView


      您的項目需求咨詢熱線:0760-88610046(國家高新技術企業)

      *請認真填寫需求,我們會在24小時內與您取得聯系。

      国产无套粉嫩白浆内精_国产精品无卡毛片视频_国产一区二区精品久久岳_亚洲怡红院久久精品综合