手機屏幕對角線的物理尺寸。單位英寸(inch),一英寸大約 2.54cm。常見的手機屏幕尺寸有 4.7 英寸、5.0英寸、5.5 英寸、6.0 英寸等。android
像素(英語:Picture Element),Pixel 的縮寫。液晶屏顯示圖像,放大來看是一個個小點組成的,這些小點就是像素點。git
分辨率(英語:Image resolution),又稱解析度、解像度,能夠從顯示分辨率與圖像分辨率兩個方向來分類。github
在 Android 設備中指的是顯示分辨率,即屏幕分辨率。也就是屏幕所能顯示的像素有多少,好比:手機分辨率 1920 x 1080。算法
在圖片中指是圖像分辨率,則是單位英寸中所包含的像素點數。好比:圖片分辨率 600 x 400。json
每英寸點數(英語:Dots Per Inch,縮寫:DPI)是一個量度單位,用於點陣數碼影像,指每一英寸長度中,取樣、可顯示或輸出點的數目。服務器
通常用於打印機、鼠標等設備分辨率的度量單位。網絡
好比:打印機輸出可達 600 DPI 的分辨率,表示打印機能夠在每一平方英寸的面積中能夠輸出 600 x 600 = 360000 個輸出點。app
鼠標的 DPI 參數,指的是鼠標在桌面上移動一英寸的距離的同時,鼠標光標可以在屏幕上移動多少「點」。ide
每英寸像素(英語:Pixels Per Inch,縮寫:PPI),又被稱爲像素密度。佈局
通常用來計量計算機顯示器,電視機和手持電子設備屏幕的精細程度。一般狀況下,每英寸像素值越高,屏幕能顯示的圖像也越精細。
當咱們把相同分辨率的圖片,放在具備相同像素顯示的屏幕上顯示時。每個像素,屏幕上對應一個點顯示,此時 DPI = PPI。 好比:咱們把分辨率爲 m x n
的圖片,放在最大支持 m x n
像素的屏幕上時,DPI = PPI。
可是,實際上,咱們所須要顯示圖片的分辨率,跟屏幕參數匹配的機率仍是很小的。咱們來分析下,不匹配時的狀況:
當咱們把 1280 x 720
的圖片,放在 800 x 480
的 4 英寸的屏幕與 1920 x 1080
的 5.5 英寸的屏幕上顯示時的結果爲:
PPI 是屏幕的顯示性能,因此與顯示的圖片沒有關係,是固定的值,可是 DPI 與顯示的圖片是有關係的。
1280 x 720
的圖片放在 800 x 480
的 4 英寸的屏幕上顯示雖然圖片一行有 720 個像素,可是屏幕一行最多隻能顯示 480 個點,因此 DPI = PPI = 233
,已經達到屏幕的最大顯示能力。
1280 x 720
的圖片放在 1920 x 1080
的 5.5 英寸的屏幕上顯示雖然屏幕一行有 1080 個點,可是圖片一行最多隻能顯示 720 個像素,因此 DPI = 267 < PPI
,並未達到屏幕的最大顯示能力,未達到屏幕的最佳顯示效果。
經過上面分析能夠獲得:
一句話總結下就是 DPI 表示印刷品點的密度,PPI 表示顯示設備點的密度。
因爲顯示器的 DPI 是固定的,不像打印機那樣能夠調整,因此針對顯示器的設計時 DPI = PPI。
計算顯示器的每英寸像素值,須要肯定屏幕的尺寸和分辨率。
其中:
根據屏幕每英寸像素值的不一樣,Android 中將平板電腦和手機的屏幕分爲下面幾類:
密度名稱 | 每英寸像素值 | 圖標尺寸 |
---|---|---|
低密度(LDPI) | ~120dpi | 36 x 36 px |
中密度(MDPI) | 120dpi ~ 160dpi | 48 x 48 px |
高密度(HDPI) | 160dpi ~ 240dpi | 72 x 72 px |
超高密度(XHDPI) | 240dpi ~ 320dpi | 96 x 96 px |
超超高密度(XXHDPI) | 320dpi ~ 480dpi | 144 x 144 px |
超超超高密度(XXXHDPI) | 480dpi ~ 640dpi | 192 x 192 px |
DP 或者 DIP,是 Android 開發用的單位。1dp 表示在屏幕點密度爲 160ppi 時 1px 長度。
因爲 Android 設備屏幕衆多,不可能爲每一個屏幕單獨開發,因此用下面公式計算在不一樣屏幕上的像素數。
同一圖標在分辨率不一樣的設備上顯示時,會出現以下效果:
能夠看到上圖第 1 和第 2 個設備兩個屏幕尺寸相同,因爲它們分辨率的不一樣,同一個圖標在兩個設備上顯示的尺寸相差很大。
那麼,圖片顯示大小是由什麼決定的呢,屏幕尺寸嗎?上圖第 1 和第 2 個設備屏幕都是 4.3 英寸。
仍是由於分辨率呢?上圖第 2 和第 3 個設備屏幕都是 720 x 1280 的分辨率。
最後咱們找到了像素密度(density),也就是像素數和屏幕尺寸的比值。density 是每單位長度容納的像素數量,通常用像素/英寸,也就是 Pixel per inch(PPI)。
對比上圖能夠知道,PPI 越低圖片顯示的越大,PPI 越高圖片顯示的越小。
要讓不一樣屏幕顯示圖片的大小相同,就須要對圖片進行縮放,給高 PPI 屏提供更大的圖片。
高 PPI 屏幕須要更大的圖片才能獲得一樣的顯示效果,反之亦然。
PPI 和圖片 px 的關係,以下:
選定一個 PPI 值做爲基礎繪製圖片,用 PPI 的比值計算出圖片縮放比例,就能夠適配各類屏幕。
Android 選定的這個基礎值就是 160ppi
。
咱們已經解決了圖片放大縮小的問題,還須要一個單位用來描述長度。
由於 px 不固定,inch 不方便,因此 Android 創造了一個新的單位 dp,中文名密度無關像素。而且規定在 160ppi 的屏幕上 1dp = 1px。
設計師只須要針對 160ppi 的顯示屏設計並製圖,安卓會根據當前手機屏幕的 PPI 值來放大縮小圖片,在不一樣的屏幕上獲得相近的顯示效果。
Android 設備的文字單位是 SP,簡單理解和 DP 是相同的。另外 SP 會隨着系統的字體大小改變,而 DP 則不會。
Google 推薦咱們使用 12sp 以上的大小,一般可使用 12sp、14sp、18sp、22sp。最好不要使用「奇數」和「小數」。
設置視圖的寬高爲 wrap_content 時,視圖大小會根據內容自動增長。
設置視圖寬高位 match_parent 時,視圖大小始終與父級同樣大。
LinerLayout 是一個視圖組,用於使全部子視圖在單個方向(垂直或水平)保持對齊。 可使用 android:orientation
屬性指定佈局方向。
使用線性佈局時,將某一個或者多個子視圖的寬或者高設置爲 0dp
,設置 weight 值爲 1
。
weight 值爲 1 的子視圖將會充滿父視圖剩餘的空間,若是設置多個子視圖的 weight 都爲 1,那麼這些子視圖將平分並充滿父視圖剩餘的空間。
RelativeLayout 是一個視圖組,顯示相對位置的子視圖。使用 RelativeLayout 能夠將子視圖定位在任意位置。
使用方式以下:
|- layout // 無限定符,默認佈局
|- main.xml
|- layout-small // 小屏幕設備
|- main.xml
|- layout-normal // 中等屏幕設備
|- main.xml
|- layout-large // 大屏幕設備
|- main.xml
|- layout-xlarge // 超大屏幕設備
|- main.xml
複製代碼
最小寬度限定符就是設置設備屏幕大於或等於最小寬度時加載的視圖。
例如,7 英寸平板電腦最小寬度爲 600dp,若是但願的 UI 在這些屏幕上顯示兩列,但在較小屏幕上顯示單列,就可使用最小寬度限定符。
|- layout // 無限定符,默認佈局顯示單列
|- main.xml
|- layout-sw600dp // 設備寬度爲 600dp 以上時顯示兩列
|- main.xml
複製代碼
若是適配的屏幕設備比較多,爲了方便視圖文件的管理,咱們可使用佈局別名。
|- layout
|- main.xml // 單列布局
|- main_twopanes.xml // 雙列布局
|- values-large
|- layout.xml
|- values-sw600dp
|- layout.xml
複製代碼
res/values-large/layout.xml
:<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
複製代碼
res/values-sw600p/layout.xml
:<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
複製代碼
後兩個文件內容徹底相同,但它們實際上並未定義佈局, 而只是將 main
設置爲 main_twopanes
的別名。因爲這些文件具備 large
和 sw600dp
選擇器,所以它們適用於任何 Android 版本的平板電腦和電視(低於 3.2 版本的平板電腦和電視匹配 large
,高於 3.2 版本者將匹配 sw600dp
)。
|- layout
|- main.xml // 單列布局
|- main_twopanes.xml // 雙列布局
|- values-large-land // 大屏幕橫向
|- layout.xml
|- values-sw600dp-port // 最小寬度 600dp 橫向
|- layout.xml
複製代碼
官方建議的圖標尺寸:
密度名稱 | 每英寸像素值 | 圖標尺寸 | 圖片資源目錄 |
---|---|---|---|
LDPI | ~120dpi | 36 x 36 px | mipmap-ldpi |
MDPI(基準) | 120dpi ~ 160dpi | 48 x 48 px | mipmap 或 mipmap-mdpi |
HDPI(1.5倍) | 160dpi ~ 240dpi | 72 x 72 px | mipmap-hdpi |
XHDPI(2倍) | 240dpi ~ 320dpi | 96 x 96 px | mipmap-xhdpi |
XXHDPI(3倍) | 320dpi ~ 480dpi | 144 x 144 px | mipmap-xxhdpi |
XXXHDPI(4倍) | 480dpi ~ 640dpi | 192 x 192 px | mipmap-xxxhdpi |
按照官方密度類型進行切圖便可,通常狀況下只須要根據主流設備選擇所須要的資源文件便可。
目前已知主流設備屏幕:
屏幕分辨率 | 屏幕尺寸 | PPI | 對應密度 | 圖片資源文件夾 |
---|---|---|---|---|
240 x 320 | 2.5 | 160 | MDPI(基準) | drawable-mdpi |
400 x 800 | 4.0 | 224 | HDPI(1.5倍) | drawable-hdpi |
720 x 1280 | 4.7 | 313 | XHDPI(2倍) | drawable-xhdpi |
1080 x 1920 | 5.5 | 401 | XXHDPI(3倍) | drawable-xxhdpi |
1440 x 2560 | 6.0 | 490 | XXXHDPI(4倍) | drawable-xxxhdpi |
紅色框區域:表示縱向拉伸的區域,當圖片須要縱向拉伸的時候它會只指定拉伸紅色區域,其餘區域在縱向是不會拉伸。
綠色框區域:表示橫向拉伸的區域,當圖片須要橫向拉伸的時候它會只指定拉伸綠色區域,其餘區域在橫向是不會拉伸的。
顯然紅色和綠色相交的部分是既會進行橫向拉伸也會進行縱向拉伸。
黃色區域:表示前景能顯示的橫向範圍。即前景的最左邊能夠顯示到什麼地方,最右邊能夠顯示的什麼地方。
藍色區域:表示前景能顯示的縱向範圍。即前景的最上面能夠顯示到什麼地方,最下面能夠顯示的什麼地方。
藍色和黃色相交部分:表示整個前景能顯示的區域。一個區域是矩形的,藍色規定了上下邊界,黃色規定了左右邊界,二者共同固然也就規定了一個矩形區域。
矢量圖是根據幾何特性來繪製圖形,矢量能夠是一個點或一條線,矢量圖只能靠軟件生成,文件佔用內在空間較小,由於這種類型的圖像文件包含獨立的分離圖像,能夠自由無限制的從新組合。
它的特色是放大後圖像不會失真,和分辨率無關,適用於圖形設計、文字設計和一些標誌設計、版式設計等。
SVG 指可伸縮矢量圖形 (Scalable Vector Graphics)。用來定義用於網絡的基於矢量的圖形,SVG 使用 XML 格式定義圖形,圖像在放大或改變尺寸的狀況下其圖形質量不會有所損失。
Android 中對矢量圖的支持就是對 SVG 的支持。使用方式比較簡單,這裏再也不贅述。
ImageView 是 Android 中最經常使用的控件之一,而在使用 ImageView 時,必不可少的會使用到它的 scaleType 屬性。該屬性指定了你想讓 ImageView 如何顯示圖片,包括是否進行縮放、等比縮放、縮放後展現位置等。
Android 提供了八種 scaleType的 屬性值,每種都對應了一種展現方式。
本地加載圖片時,根據設備屏幕分辨率或像素密度,向服務器請求對應級別的圖片資源。
Android P 提供提供的劉海屏適配方案,詳見:Android 開發文檔 - 支持顯示切口
劉海屏適配思路:
LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
可將劉海區域變成一條黑色邊)。若是全屏顯示,獲取到危險區域(劉海區域),讓操做區域避開危險區域便可。Google 建議咱們支持更多的設備,可是根據需求可能須要不支持某些設備。好比,僅支持手機不支持平板電腦。咱們就能夠增長不支持的屏幕設備。
若是應用僅支持小屏幕尺寸和標準屏幕尺寸,能夠這麼作:
<manifest ... >
<compatible-screens>
<!-- 全部的小尺寸屏幕 -->
<screen android:screenSize="small" android:screenDensity="ldpi" />
<screen android:screenSize="small" android:screenDensity="mdpi" />
<screen android:screenSize="small" android:screenDensity="hdpi" />
<screen android:screenSize="small" android:screenDensity="xhdpi" />
<!-- 全部的標準尺寸屏幕 -->
<screen android:screenSize="normal" android:screenDensity="ldpi" />
<screen android:screenSize="normal" android:screenDensity="mdpi" />
<screen android:screenSize="normal" android:screenDensity="hdpi" />
<screen android:screenSize="normal" android:screenDensity="xhdpi" />
</compatible-screens>
...
<application ... >
...
<application>
</manifest>
複製代碼
若是應用僅支持平板電腦或電視,能夠這麼作:
<manifest ... >
<supports-screens android:smallScreens="false" android:normalScreens="false" android:largeScreens="true" android:xlargeScreens="true"/>
...
</manifest>
複製代碼
2018 年 5 月,字節跳動技術團隊提出了一種低成本的屏幕適配方式,強烈推薦你們看一下:一種極低成本的 Android 屏幕適配方式
歡迎關注個人公衆號,分享各類技術乾貨,各類學習資料,職業發展和行業動態。
歡迎加入技術交流羣,來一塊兒交流學習。