2018-05-20
前言
一款Android 螢幕適配方案。
網上關於螢幕適配的文章已經鋪天蓋地了,為什麼我還要講?因為網上現在基本都是使用px適配,即每種螢幕解析度的裝置需要定義一套dimens.xml檔案。再加上有些手機還有虛擬按鍵(例如華為),這樣就還需要每個有虛擬按鍵的裝置加多一套dimens.xml檔案,再加上平板那些你會發現dimens.xml檔案所佔的體積已經超過2M了!這絕對不是我們想要的。
我這裡要講的是使用dp來進行適配(Google推薦的也是這種方式),使用這種方式專案中多套dimens.xml檔案才佔幾百K,而且根本不用考慮虛擬按鍵的問題。這種方案已經在自己多個專案中應用過了,經過幾十臺手機測試過,基本不會出現適配有問題的情況。製作生成對應dimens.xml檔案外掛的作者(後面會講)ofollow,noindex">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值來等比縮放而已。
問題:
-
既然原理都一樣,都需要多套dimens.xml檔案,為什麼說dp適配就比px適配好呢?
因為px適配是根據螢幕解析度的,Android裝置解析度一大堆,而且還要考慮虛擬鍵盤。而dp適配無論手機螢幕的畫素多少,密度比值多少,80%的手機的最小寬度dp值(widthPixels / density)都為360dp,這樣就大大減少了dimens.xml檔案。
-
px適配會根據裝置的解析度去找對應的dimens.xml檔案(如下圖,執行在解析度為1920x1080的手機上,系統會自動找到對應的values-1920x1080檔案),那dp適配呢?
[圖片上傳失敗...(image-86fd53-1541728256699)]
dp適配也是一樣的,只不過dp適配是根據“最小寬度(Smallest-width)限定符” 來找的,需要注意的是“最小寬度”是不區分方向的,即無論是寬度還是高度,哪一邊小就認為哪一邊是“最小寬度”。所以如果當前裝置最小寬度(以 dp 為單位)為400dp,那麼系統會自動找到對應的values-sw400dp資料夾下的dimens.xml檔案,如圖
[圖片上傳失敗...(image-8967ad-1541728256699)]
獲取裝置最小寬度程式碼,
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阿杜 提供了自動生成工具。
工具使用步驟:
- 在Android Studio中安裝ScreenMatch外掛,如圖:
[圖片上傳失敗...(image-fdee03-1541728256699)]
-
在專案的預設values資料夾中需要一份dimens.xml檔案
我在github原始碼已經提供了一份,直接複製過來即可。
[圖片上傳失敗...(image-de366b-1541728256699)]
github地址:Adaptation" target="_blank" rel="nofollow,noindex">ScreenAdaptation
-
執行生成
外掛安裝好後,在專案的任意目錄或檔案上右鍵,選擇ScreenMatch選項。如圖:
[圖片上傳失敗...(image-578b15-1541728256699)]
然後選擇在哪個module下執行適配。
即基於哪個module下的res/values/dimens.xml檔案作為基準dimens.xml檔案,生成的其他尺寸dimens.xml檔案放在哪個module下。
[圖片上傳失敗...(image-48dbb3-1541728256699)]
點選確定就會執行生成命令,如下代表生成成功。
[圖片上傳失敗...(image-ff6d3c-1541728256699)]
然後再看看res目錄下會自動生成一堆dimens.xml檔案,如下:
[圖片上傳失敗...(image-e4114a-1541728256699)]
通過上面的步驟就已經生成了所有裝置對應的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檔案)。配置檔案在我們執行完成上面的命令後,會在專案的目錄下自動生成,如下:
[圖片上傳失敗...(image-d7d77-1541728256699)]
開啟檔案,修改下面的值即可。如下只需要適配384,392,400,410,411的值,不需要適配480,533,592,600,640,662,720,768,800,811,820,960,961,1024,1280,1365的值
[圖片上傳失敗...(image-92e18-1541728256699)]
其中base_dp=360代表widthDP基準值,一般都是360dp,不建議更改,除非你對螢幕適配原理有深刻的見解。
當然!這些步驟你可以全部都不用做。直接複製我github上的各個dimens.xml檔案到你專案即可!這些都是我在真實專案中使用的。
2、根據設計圖標註,在佈局寫上對應的值。
在安卓中,系統密度為160dpi的中密度手機螢幕為基準螢幕,即320×480的手機螢幕。在這個螢幕中,1dp=1px。320x480解析度對應的其他解析度的比例如下:
[圖片上傳失敗...(image-3f8d15-1541728256699)]
圖片來源:UI設計師不可不知的安卓螢幕知識
所以,如果UI給的是720x1280解析度的圖, 那麼dp = px / 2, 給的是1080x1920解析度的圖,那麼 dp = px / 3,即根據比例即可。
舉例:UI在720x1280上做的圖,其中一個按鈕的寬高分辨為:寬720px,高為100px,字型大小為30px,在佈局中則這樣使用:
<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值
怎麼適配其他module?
- 問題:在專案的其他module中怎麼實現適配?難道也要多套dimens?
- 解決:並不需要多套dimens,只需要在values資料夾下有一套與app module一樣的dimens檔案即可達到適配。因為經過編譯,所有module中的dimen資料都會統一歸類到主module(即app module)中的values/dimens.xml檔案中了,然後系統又會根據你設定的值去找對應values-swxxxdp資料夾下的dimens.xml檔案中的值。
- 驗證:在專案中建一個module,然後隨便取一個dimens.xml檔案中的值進行列印,分別執行在不同widthDP的裝置上(用模擬器即可)觀察列印的結果發現確實是這樣的。
最後非常感謝大神android阿杜 提供的外掛,具體的dp適配與外掛原理可以去看看他寫的文章。
github地址:ScreenAdaptation
參考資料:
- Android螢幕適配全攻略(最權威的官方適配指導)
- Android 螢幕適配:最全面的解決方案
- Android 螢幕適配方案
- Android dp方式的螢幕適配工具使用(Android Studio外掛方式)
作者:wildma
連結:https://www.jianshu.com/p/1302ad5a4b04
來源:簡書
這是轉載別人的東西。樓主親測。還是可以的。上面的連結就是作者本人的。