天天看點

安卓螢幕适配方案(根據今日頭條方案,更新版)

前言

螢幕适配方案有很多,比如原生的dp,鴻洋大神的AutoLayout,寬高限定符,今天我用缺點比較小的今日頭條方案

頭條适配方案的文章連結:https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA

使用效果

測試後可以适配我身邊的所有機型(其他的應該是都可以)

  • 設定Activity後Activity可以适配
  • 設定Activity後Activity内的Fragment可以适配
  • 設定Activity後Activity内的RecyclerView可以适配
  • 設定Activity後Activity彈出的Dialog可以适配

優缺點

優點:适配簡單,無侵入,調用簡單,未使用非官方api,不影響性能

缺點:基本可以通過騷操作來避免

使用方式

複制工具類

import android.app.Activity;
import android.util.DisplayMetrics;

/**
 * 創    建:  lt  2018/8/15--14:45
 * 作    用:  使用并優化今日頭條的适配方案的工具類
 * 注意事項:  在Activity的onCreate裡,并在setContextView之上調用,可以直接放在Base裡
 */

public class FitUtil {
    private static float width = 750;//todo 手動設定為設計圖的寬(px),适配将根據寬為基準,也可以設定高,但是推薦設定寬,如果不需要px=dp則不設定也行
    private static int dpi = 375;//todo 手動設定設計圖的dpi,一般 xhdpi是寬/2 xxhdpi 是寬/3
    private static float nativeWidth = 0;//真實螢幕的寬,不需要手動改

    /**
     * 在Activity的onCreate中調用,修改該Activity的density,即可完成适配,使用寬高直接使用設計圖上px相等的dp值
     *
     * @param activity     需要改變的Activity
     * @param isPxEqualsDp 是否需要設定為設計圖上的px直接在xml上寫dp值(意思就是不需要自己計算dp值,直接寫設計圖上的px值,并改機關為dp),但開啟後可能需要手動去設定ToolBar的大小,如果不用可以忽略
     */
    public static void autoFit(Activity activity, boolean isPxEqualsDp) {
        if (nativeWidth == 0) {
            //保證取到的是真實的寬,而不是旋轉後的寬
            Point outSize = new Point();
            activity.getWindowManager().getDefaultDisplay().getSize(outSize);
            nativeWidth = Math.min(outSize.x, outSize.y);
        }
        DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
        displayMetrics.density = isPxEqualsDp ? nativeWidth / dpi / (width / dpi) : nativeWidth / dpi;
        displayMetrics.densityDpi = (int) (displayMetrics.density * 160);
    }
}
           

使用

在Activity的onCreate裡,并在setContextView之上調用,可以直接放在Base裡,比如:

public class BaseActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FitUtil.autoFit(this,false);//this
    }
}
           

手動設定好UI給你的設計圖的寬和dp(請檢視注釋自行計算)

機關用dp,字型機關也用dp,就可以自動适配了

需要注意方法的第二個參數

如果UI給你的圖紙是按照dp為機關,就設定為false,然後頁面上直接寫相應的dp值就ok

如果UI給你的圖紙是按照px為機關,就設定為true,然後頁面上寫對應的px值,但是機關寫成dp,相當于直接從UI設計圖上抄下來,很友善

但是推薦設定為false,如果設計圖紙是px為機關則自行計算,因為設定為true會使其他的三方View變得偏小

某些可以避免的坑

  1. 字型機關的坑,sp可以通過修改scaledDensity屬性來修改,不過為了防止使用者調節字型導緻字型顯示不全,是以推薦使用dp,而不用去修改scaledDensity屬性
  2. 聽說8.0手機無效,不過我在自己的8.0手機上可以(華為)
  3. 本方案對純豎屏應用支援較好,若是純橫屏或橫豎屏相交叉的話需要自行修改方法即可

擴充

由于px=dp方案留有一些坑(三方View架構也會用到dp值,而部分無法手動去修改),是以該px=dp的方案并不推薦使用,但是若小夥伴又想如此适配,又想使用px=dp方案的話,接下來我會提供一下騷操作供參考

檢視源碼可知,系統在使用距離值的時候會把所有的機關值轉換為px值來應用,而轉換方法如下:

TypedValue.java下
public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }
           

可以看到系統提供了六種機關,上面就是修改了dp的計算系數來适配螢幕,而一些三方架構可能會使用dp,sp甚至是px來給View設定寬高,是以可以将目光放在基本不用的機關上

騷操作來了

我們可以使用in這個機關(英寸),修改方法:

public static void autoFit2(Activity activity, boolean isPxEqualsDp) {
        if (nativeWidth == 0) {
            nativeWidth = activity.getWindowManager().getDefaultDisplay().getWidth();
        }
        DisplayMetrics displayMetrics = activity.getResources().getDisplayMetrics();
        displayMetrics.xdpi = isPxEqualsDp ? nativeWidth / dpi / (width / dpi) : nativeWidth / dpi;
    }
           

然後所有值抄設計圖上的,機關用in,則可以解決上述問題

親測可以使用,并且适配三方架構,也不會影響到系統控件;但,該方案缺點也有,是以該方案僅供參考

  1. 預覽慘不忍睹,因為in機關是英寸,手機才幾英寸,而View的值動不動就是幾十幾百的,預覽時基本上就是一個控件占滿螢幕
  2. 由于本人隻是測試了該方案(n多種情況下),但是并沒有正式用在項目上,是以會不會出現奇葩情況也不得而知
  3. 由于修改了xdpi,測試過程中并沒有什麼其他變化,但目前不清楚修改後會不會有其他的影響(檢視源碼看到引用該值的地方并不多)
  4. 由于該操作屬于比較騷的操作,是以可能不會得到認可(哈哈)

是以上面的幾種方案需要自行選擇判斷

轉載請帶上本文連結,然後點個贊