1. 程式人生 > >dimens-Android非常簡單非常好用的螢幕適配

dimens-Android非常簡單非常好用的螢幕適配

為什麼要進行Android螢幕適配?

關於為什麼要進行Android螢幕適配,什麼是dp、dpi這些概念我就不去一一講解了,網上很多文章。這裡我推薦幾篇講的比較好的:

px與dp適配的原理

  • px適配原理:
    根據裝置螢幕的解析度各自寫一套dimens.xml檔案,然後根據一個基準解析度(例如720x1080),將寬度分成720份,取值為1px——720px,將高度分成1080份,取值為1px——1080px。生成各自dimens.xml檔案對應的值。

  • dp適配原理:
    dp適配原理與px適配一樣,區別就在於px適配是根據螢幕解析度,即拿px值等比例縮放,而dp適配是拿dp值來等比縮放而已。

問題:

  1. 既然原理都一樣,都需要多套dimens.xml檔案,為什麼說dp適配就比px適配好呢?
    因為px適配是根據螢幕解析度的,Android裝置解析度一大堆,而且還要考慮虛擬鍵盤。而dp適配無論手機螢幕的畫素多少,密度比值多少,80%的手機的最小寬度dp值(widthPixels / density)都為360dp,這樣就大大減少了dimens.xml檔案。

  2. px適配會根據裝置的解析度去找對應的dimens.xml檔案(如下圖,執行在解析度為1920x1080的手機上,系統會自動找到對應的values-1920x1080檔案),那dp適配呢?

     

dp適配也是一樣的,只不過dp適配是根據“最小寬度(Smallest-width)限定符”來找的,需要注意的是“最小寬度”是不區分方向的,即無論是寬度還是高度,哪一邊小就認為哪一邊是“最小寬度”。所以如果當前裝置最小寬度(以 dp 為單位)為400dp,那麼系統會自動找到對應的values-sw400dp資料夾下的dimens.xml檔案,如圖

 

獲取裝置最小寬度程式碼,

        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int heightPixels = dm.heightPixels;
        int widthPixels = dm.widthPixels;
        float density = dm.density;
        float heightDP = heightPixels / density;
        float widthDP = widthPixels / density;
        float smallestWidthDP;
        if(widthDP < heightDP) {
            smallestWidthDP = widthDP;
        }else {
            smallestWidthDP = heightDP;
        }

使用步驟

1、以某一widthDP為基準,生成所有裝置對應的dimens.xml檔案

生成這些檔案當然不會手動去寫,網上已經有大神android阿杜提供了自動生成工具。

工具使用步驟:

  1. 在Android Studio中安裝ScreenMatch外掛,如圖:

  1. 在專案的預設values資料夾中需要一份dimens.xml檔案
    我在github原始碼已經提供了一份,直接複製過來即可。

github地址:ScreenAdaptation

  1. 執行生成
    外掛安裝好後,在專案的任意目錄或檔案上右鍵,選擇ScreenMatch選項。如圖:

然後選擇在哪個module下執行適配。
即基於哪個module下的res/values/dimens.xml檔案作為基準dimens.xml檔案,生成的其他尺寸dimens.xml檔案放在哪個module下。

點選確定就會執行生成命令,如下代表生成成功。

然後再看看res目錄下會自動生成一堆dimens.xml檔案,如下:

通過上面的步驟就已經生成了所有裝置對應的dimens.xml檔案。

因為預設生成的是下列最小寬度dp的dimens.xml檔案
384,392,400,410,411,480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365,如果不需要或者需要增加某些dp值的dimens.xml檔案,則需要修改配置檔案,即screenMatch.properties檔案(修改前先刪除之前生成的全部dimens.xml檔案)。配置檔案在我們執行完成上面的命令後,會在專案的目錄下自動生成,如下:

開啟檔案,修改下面的值即可。如下只需要適配384,392,400,410,411的值,不需要適配480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365的值

其中base_dp=360代表widthDP基準值,一般都是360dp,不建議更改,除非你對螢幕適配原理有深刻的見解。

當然!這些步驟你可以全部都不用做。直接複製我github上的各個dimens.xml檔案到你專案即可!這些都是我在真實專案中使用的。

2、根據設計圖標註,在佈局寫上對應的值。

在安卓中,系統密度為160dpi的中密度手機螢幕為基準螢幕,即320×480的手機螢幕。在這個螢幕中,1dp=1px。320x480解析度對應的其他解析度的比例如下:

image.png

圖片來源:UI設計師不可不知的安卓螢幕知識

所以,如果UI給的是720x1280解析度的圖, 那麼dp = px / 2, 給的是1080x1920解析度的圖,那麼 dp = px / 3,即根據比例即可。

舉例:UI在720x1280上做的圖,其中一個按鈕的寬高分辨為:寬720px,高為100px,字型大小為30px,在佈局中則這樣使用:

注:Android系統不設定字型大小的話,預設是@dimen/sp_14

    <Button
        android:layout_width="@dimen/dp_360"
        android:layout_height="@dimen/dp_50"
        android:textSize="@dimen/sp_15"/>

程式碼中動態設定dp或sp:
如果需要在程式碼中動態設定dp或sp,則需要通過getDimension()方法獲取對應資原始檔下的dp或sp值再設定(具體參考github上的demo)。如下:

 

        /*獲取sp值*/
        float pxValue = getResources().getDimension(R.dimen.sp_15);//獲取對應資原始檔下的sp值
        int spValue = ConvertUtils.px2sp(this, pxValue);//將px值轉換成sp值
        mTvShowParams.setTextSize(spValue);//設定文字大小

        /*獲取dp值*/
        float pxValue2 = getResources().getDimension(R.dimen.dp_360);//獲取對應資原始檔下的dp值
        int dpValue = ConvertUtils.px2dp(this, pxValue2);//將px值轉換成dp值



 mTv_file_type.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX,getResources().getDimension(R.dimen.sp_15));


怎麼適配其他module?

  • 問題:在專案的其他module中怎麼實現適配?難道也要多套dimens?
  • 解決:並不需要多套dimens,只需要在values資料夾下有一套與app module一樣的dimens檔案即可達到適配。因為經過編譯,所有module中的dimen資料都會統一歸類到主module(即app module)中的values/dimens.xml檔案中了,然後系統又會根據你設定的值去找對應values-swxxxdp資料夾下的dimens.xml檔案中的值。
  • 驗證:在專案中建一個module,然後隨便取一個dimens.xml檔案中的值進行列印,分別執行在不同widthDP的裝置上(用模擬器即可)觀察列印的結果發現確實是這樣的。