0. 前言
Android的螢幕適配,即使得某一元素在Android不同尺寸、不同解析度的手機上具備相同的顯示效果,這個問題一直以來都是我們Android開發人員不得不面對的問題。本文參考了很多前人的部落格,並對這一問題做一個總結,力求精簡明了。
轉載請註明出處:http://blog.csdn.net/seu_calvin/article/details/52690498
1. 基礎概念
(1)螢幕尺寸,即手機對角線的物理尺寸
1英寸 = 2.54cm 常見手機尺寸有5英寸、5.5英寸、6英寸等。
(2)螢幕解析度,即手機在橫向、縱向上的像素點數總和(一般描述成螢幕的”寬x高”)
例如1080dpx1920dp,即寬度方向上有1080個像素點,在高度方向上有1920個像素點,1px=1像素點
Android手機常見的解析度:320x480、480x800、720x1280、1080x1920
(3)螢幕像素密度,即每英寸的像素點數,單位dpi
例如某裝置為240x320,螢幕尺寸為3.3英寸,那麼該裝置的螢幕像素密度為400/3.3=120dpi,其中400為通過寬高像素勾股定理得出。
Android手機根據像素密度,可以分為以下幾種螢幕密度類型:
(4)密度無關像素,單位為dp,是Android特有的單位
Android開發時通常使用dp而不是px單位設定圖片大小,因為它可以保證在不同螢幕像素密度的裝置上顯示相同的效果。
/** * dp與px的轉換 * Created by SEU_Calvin on 2016/09/28 */ public class DensityUtils { public static int dp2px(float dp , Context context){ float density = context.getResources().getDisplayMetrics().density;//即表中的0.75/1/1.5/2/3 //context.getResources().getDisplayMetrics().densityDpi //即表中的120/160/240/320/480 return (int)(dp * density + 0.5f); } public static float px2dp(int px , Context context){ float density = context.getResources().getDisplayMetrics().density; return px/density; } }
(5)獨立比例像素,單位為sp,Android開發時用於設定文字大小的單位
可根據字型大小喜好設定進行縮放,推薦使用12/14/18/22sp作為字型設定的大小,不推薦使用奇數和小數,容易造成精度的丟失問題。
介紹了上述基礎概念,我們接下來從布局適配、圖片適配、以及代碼適配三個角度分別介紹螢幕適配的解決方案。
2. 布局適配
(1)推薦使用相對布局,禁用絕對布局。因為相對布局在螢幕的大小改變時視圖之間的相對位置不會變化。
(2)使用dp和sp(盡量不用px)、wrap_content、match_parent和weight來控制布局。使用權重weight在任何裝置上均會完美適配。
(3)為不同螢幕尺寸的裝置設計不同的布局,通過配置限定符使得程式在運行時根據當前裝置的尺寸自動載入合適的布局資源。
比如我們先寫兩個布局檔案,分別為:
適配手機的布局(預設):res/layout/main.xml
適配尺寸>7寸平板的布局:res/layout/main_pb.xml
然後加入以下兩個檔案,系統會根據Android版本自動選擇使用哪個布局設定檔。
//適配Android 3.2之前的平板布局 res/values-large/layout.xml <resources> <item name="main" type="layout">@layout/main_pb</item> </resources> //適配Android 3.2之後的平板布局 res/values-sw600dp/layout.xml <resources> <item name="main" type="layout">@layout/main_pb</item> </resources>
上述兩個設定檔,並沒有真正去定義布局,它們僅僅是將main設定成了@layout/main_pb的別名。
如果不這樣做,main_pb.xml布局檔案的內容需要複製成兩份分別放入res/layout-large/main.xml和res/layout-sw600dp/main.xml以適配3.2以前和以後,這樣明顯很冗餘。
3. 圖片適配
(1)比如有一個這樣的需求,一個按鈕的背景圖片必須能夠隨著按鈕大小的改變而改變。使用普通的圖片將無法實現上述功能,因為運行時會均勻地展開或壓縮你的圖片。
這時候可以使用Nine-Patch圖(一種被特殊處理過的PNG圖片,使用.9.png尾碼名),9Patch圖可以指定圖片的展開地區和非展開地區,在需要展開圖片時,系統就會自動地展開你想要展開的部分。需要注意的是,.9圖不需要多個解析度的圖片,放在drawable檔案夾即可。
紅色框地區:表示縱向展開的地區,也就是說,當圖片需要縱向展開的時候它會只指定展開紅色地區。
綠色框地區:表示橫向展開的地區,也就是說,當圖片需要橫向展開的時候它會只指定展開綠色地區。
(2)圖片不需要在下圖hdpi、mdpi等目錄下都放入相對應的解析度的圖片,這樣會使APK變大,一般只做1280*720一套圖,放在hdpi或xhdpi下,若出問題再針對螢幕進行問題圖片替換即可。另外對於如何減小APK大小,可以參考Android開發——減小APK大小。
3. 代碼適配
(1)比如有一個需求,需要實現一個空間寬度,是螢幕的1/3。這時候就可以用代碼實現:
/** * 代碼適配例子 * Created by SEU_Calvin on 2016/09/28 */ WindowManager wm = getWindowManager(); int width = wm.getDefaultDisplay().getWidth(); LinearLayout.LayoutParams params = (LayoutParams)tv.getLayoutParams(); params.width = width/3; tv.setLayoutParams(params);
需要注意的是,一般代碼適配需要寫一個工具類(上文中已經貼出了)來實現dp2px ,因為代碼裡的參數一般都需要px值,需要通過不同裝置的螢幕密度來實現dp2px。
(2)代碼適配的另一個使用情境是根據載入布局的不同,來決定走不同的流程,如下:
setContentView(R.layout.main_layout);//此處會根據螢幕大小載入不同的布局 Button btn = (Button)findViewById(R.id.btn);//其中一個布局沒有該按鈕 if(btn == null){ //商務邏輯1... }else{ //商務邏輯2... }
感謝閱讀,希望能協助到大家,謝謝大家對本站的支援!