Android 裝置不僅有各種螢幕大小 (手機、平板電腦、電視等),且螢幕像素尺寸不同。一部裝置的每英寸像素數可能為 160 像素,而另一部裝置的像素在相同空間中則符合 480 像素。如果您未考慮像素密度的這些變化,系統可能會縮放圖片,導致圖片模糊不清,或者顯示的圖片尺寸不正確。
本頁將說明如何使用與解析度不同的測量單位,以及為每個像素密度提供替代點陣圖資源,設計應用程式來支援不同的像素密度。
如需這些技巧的簡介,請觀看以下影片。
如要進一步瞭解如何設計圖示素材資源,請參閱 Material Design 圖示指南。
使用密度獨立像素
避免使用像素來定義距離或大小。由於不同螢幕的像素密度不同,因此相同數量的像素會對應至不同裝置上的不同實體大小,因此使用像素定義尺寸會發生問題。

如要在不同密度的螢幕上保留 UI 的可見大小,請使用密度獨立像素 (dp) 做為測量單位來設計使用者介面。1 dp 是虛擬像素單位,約等於 160 dpi (160 dpi) 的虛擬像素密度。Android 會將這個值轉換成每個其他密度的適當實際像素數量。
請參考圖 1 中的兩部裝置。寬度為 100 像素的檢視畫面在裝置左側的裝置上顯得比它還要大。定義寬度為 100 dp 的檢視畫面在兩個螢幕上都會顯示相同大小。
定義文字大小時,您可以改用可擴充像素 (sp) 做為單位。根據預設,sp 單位的大小與 dp 相同,但系統會根據使用者偏好的文字大小調整其大小。請勿使用 sp 設定版面配置大小。
舉例來說,如要指定兩個檢視畫面之間的間距,請使用 dp:
<Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clickme" android:layout_marginTop="20dp" />
指定文字大小時,請使用 sp:
<TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" />
將 dp 單位轉換為像素單位
在某些情況下,您需要以 dp 表示維度,然後將尺寸轉換為像素。dp 單位與螢幕像素的換算方式如下:
px = dp * (dpi / 160)
注意:如要計算像素,請不要以硬式編碼的方式將這個方程式。請改用 TypedValue.applyDimension()
,將多種維度 (dp、sp 等) 轉換為像素。
假設在使用者移動了至少 16 像素的手指後,系統才辨識出捲動或滑動手勢的應用程式。在基準螢幕上,使用者的手指必須移動 16 pixels
/ 160 dpi
(等於 1/10 英寸 (或 2.5 毫米) ),才能識別手勢。
在高密度螢幕 (240 dpi) 的裝置上,使用者的手指必須移動 16 pixels / 240 dpi
,等於 1/15 英寸 (或 1.7 公釐)。距離越短,應用程式對使用者的靈敏度也越高。
如要修正這個問題,請以 dp 表示手勢門檻,然後將其轉換為實際像素。例如:
Kotlin
// The gesture threshold expressed in dp private const val GESTURE_THRESHOLD_DP = 16.0f private var gestureThreshold: Int = 0 // Convert the dps to pixels, based on density scale gestureThreshold = TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP + 0.5f, resources.displayMetrics).toInt() // Use gestureThreshold as a distance in pixels...
Java
// The gesture threshold expressed in dp private final float GESTURE_THRESHOLD_DP = 16.0f; // Convert the dps to pixels, based on density scale int gestureThreshold = (int) TypedValue.applyDimension( COMPLEX_UNIT_DIP, GESTURE_THRESHOLD_DP + 0.5f, getResources().getDisplayMetrics()); // Use gestureThreshold as a distance in pixels...
DisplayMetrics.density
欄位會指定用於根據目前像素密度將 dp 單位轉換為像素的縮放比例係數。在中密度螢幕中,DisplayMetrics.density
等於 1.0,在高密度螢幕上則等於 1.5。在超高密度螢幕中,則等於 2.0,而低密度螢幕則等於 0.75。TypedValue.applyDimension()
會使用這張圖片取得目前畫面的實際像素數量。
使用預先縮放設定值
您可以使用 ViewConfiguration
類別存取 Android 系統的常見距離、速度和時間。舉例來說,您可以透過 getScaledTouchSlop()
取得架構使用的像素距離,藉此取得捲動門檻:
Kotlin
private val GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).scaledTouchSlop
Java
private final int GESTURE_THRESHOLD_DP = ViewConfiguration.get(myContext).getScaledTouchSlop();
無論目前的像素密度為何,在 ViewConfiguration
中以 getScaled
前置字串開頭的方法都能保證傳回可正確顯示的值 (以像素為單位)。
偏好向量圖形
與其建立多個特定密度版本的圖片,另一個方法是只建立一個向量圖形。向量圖形會使用 XML 建立圖片來定義路徑和顏色,而非使用像素點陣圖。因此,向量圖形可以縮放至任何大小,而不縮放構件,但通常最適合用於圖示等插圖,而非相片。
向量圖形通常以 SVG (Scalable Vector Graphics) 檔案提供,但 Android 不支援此格式,因此您必須將 SVG 檔案轉換成 Android 的向量可繪項目格式。
您可以使用 Android Studio 的 Vector Asset Studio 將 SVG 轉換為向量可繪項目,如下所示:
- 在「Project」視窗中的「res」目錄按一下滑鼠右鍵,然後依序選取「New」>「Vector Asset」。
- 選取「Local file (SVG, PSD)」。
找出要匯入的檔案並進行任何調整。
圖 2:使用 Android Studio 匯入 SVG。 您可能會注意到「Asset Studio」視窗中有些錯誤,表示向量可繪項目不支援檔案的部分屬性。這項操作不會阻止檔案匯入;系統會忽略不支援的屬性。
按一下「Next」。
在下一個畫面中,確認您要在專案中存放檔案的來源集,然後按一下「Finish」。
由於一個向量可繪項目可用於所有像素密度,因此這個檔案會進入預設的可繪項目目錄,如以下階層所示。您不需要使用密度專屬的目錄。
res/ drawable/ ic_android_launcher.xml
如要進一步瞭解如何建立向量圖形,請參閱向量可繪項目說明文件。
提供替代點陣圖
如要在不同像素密度的裝置上提供良好的圖像品質,請在應用程式中提供多個點陣圖版本 (每個密度值區皆以相應的解析度提供)。否則,Android 必須調整點陣圖比例,使其在每個螢幕上佔用相同的可見空間,進而產生模糊效果 (例如模糊)。

應用程式中有多種密度級別可供應用程式使用。表 1 說明可用的不同設定限定詞,以及這些限定詞適用的螢幕類型。
表 1. 不同像素密度的設定限定詞。
密度限定詞 | 說明 |
---|---|
ldpi |
適用於低密度 (ldpi) 螢幕的資源 (約 120 dpi)。 |
mdpi |
適用於中密度 (mdpi) 螢幕的資源 (約 160 dpi)。這就是基準密度。 |
hdpi |
適用於高密度 (hdpi) 螢幕的資源 (約 240 dpi)。 |
xhdpi |
適用於超高密度 (xhdpi) 螢幕的資源 (約 320 dpi)。 |
xxhdpi |
適用於超超高密度 (xxhdpi) 螢幕的資源 (約 480 dpi)。 |
xxxhdpi |
適用於 extra-extra-extra-high 像素密度 (xxxhdpi) 螢幕的資源 (約 640 dpi)。 |
nodpi |
適用於所有像素密度的資源,都屬於像素密度獨立資源。無論目前螢幕的密度為何,系統都不會縮放標有這個限定詞的資源。 |
tvdpi |
適用於 mdpi 與 hdpi 之間的螢幕資源,約 213dpi。這並不是「主要的」像素密度分組。主要用於電視,且大多數應用程式不需要使用此限定詞。如果您認為有必要提供 tvdpi 資源,請將資源大小設為 1.33 * mdpi。例如,mdpi 螢幕的 100x100 像素圖片在 tvdpi 螢幕上為 133x133 像素。 |
如要為不同密度建立替代點陣圖可繪項目,請按照 6 個主要密度之間的 3:4:6:8:12:16 縮放比例調整比例。舉例來說,如果您的點陣圖可繪項目是 48x48 像素,適用於中密度螢幕,則大小為:
- 36x36 (0.75x),適用於低密度 (ldpi)
- 48x48 (1.0x 基準),適用於中密度 (mdpi)
- 72x72 (1.5 倍),適用於高密度 (hdpi)
- 96x96 (2.0x),適用於 extra-high 像素密度 (xhdpi)
- 144x144 (3.0x),適用於超高密度 (xxhdpi)
- 192x192 (4.0x),適用於 extra-extra-extra-high 密度 (xxxhdpi)
將產生的圖片檔放在 res/
下的適當子目錄中:
res/ drawable-xxxhdpi/ awesome_image.png drawable-xxhdpi/ awesome_image.png drawable-xhdpi/ awesome_image.png drawable-hdpi/ awesome_image.png drawable-mdpi/ awesome_image.png
然後,當您參照 @drawable/awesomeimage
時,系統會根據螢幕的 dpi 選取適當的點陣圖。如果您未提供該密度的密度專屬資源,則系統會找出下一個最相符的資源,並將其縮放至適合螢幕的大小。
提示:如果您不想讓系統縮放的可繪製資源 (例如在執行階段自行對圖片執行一些調整),請將這些資源置於具有 nodpi
設定限定詞的目錄中。具有此限定詞的資源會視為各密度等級,因此系統不會縮放。
如要進一步瞭解其他設定限定詞,以及 Android 如何針對目前的螢幕設定選取合適的資源,請參閱「應用程式資源總覽」。
將應用程式圖示放在 mipmap 目錄中
與其他點陣圖素材資源一樣,您必須提供應用程式圖示的密度專屬版本。不過,部分應用程式啟動器會顯示應用程式圖示,遠多於裝置密度級別所呼叫的幅度。
舉例來說,如果裝置的密度級別為 xxhdpi,而您提供的最大的應用程式圖示位於 drawable-xxhdpi
,應用程式啟動器就會放大此圖示,讓圖示看起來較清晰。
為避免這種情況,請將所有應用程式圖示放入 mipmap
目錄中,而不是 drawable
目錄。與 drawable
目錄不同,即使您建構了特定密度的 APK,所有 mipmap
目錄都會保留在 APK 中。這可讓啟動器應用程式挑選要在主畫面上顯示的最佳解析度圖示。
res/ mipmap-xxxhdpi/ launcher_icon.png mipmap-xxhdpi/ launcher_icon.png mipmap-xhdpi/ launcher_icon.png mipmap-hdpi/ launcher_icon.png mipmap-mdpi/ launcher_icon.png
在先前的 xxhdpi 裝置範例中,您可以在 mipmap-xxxhdpi
目錄中提供較高密度的啟動器圖示。
如需圖示設計指南,請參閱「系統圖示」。
如需建構應用程式圖示的相關說明,請參閱「使用 Image Asset Studio 建立應用程式圖示」一文。
針對罕見密度問題的建議
本節說明 Android 如何針對不同像素密度執行點陣圖縮放作業,以及如何進一步控制點陣圖在不同密度上的繪製方式。除非您的應用程式操縱圖形,或是在不同的像素密度執行時發生問題,否則請忽略本節。
如要進一步瞭解如何在執行階段操控圖形時支援多種密度,您需要瞭解系統如何協助確保點陣圖的縮放比例。 運作方式如下:
- 預先縮放資源,例如點陣圖可繪項目
系統會根據目前螢幕的密度,使用應用程式中的任何密度專屬資源。如果資源在正確的密度中找不到資源,系統就會載入預設資源,並視需要縮放資源。系統會假設預設資源 (取自不含設定限定詞的目錄) 是專為基準像素密度 (mdpi) 所設計,並且會將這些點陣圖調整為適合目前像素密度的大小。
如果您要求了預先縮放資源的維度,系統會在縮放「之後」傳回代表該維度的值。舉例來說,如果點陣圖是專為 mdpi 螢幕 50x50 像素設計,在 hdpi 螢幕上就會縮放為 75x75 像素 (如果未提供 hdpi 的額外資源),而系統會回報該大小。
在某些情況下,您可能不希望 Android 預先縮放資源。如要避免預先縮放,最簡單的方法是將資源放到具有
nodpi
設定限定詞的資源目錄中。例如:res/drawable-nodpi/icon.png
當系統使用這個資料夾中的
icon.png
點陣圖時,不會根據目前的裝置密度縮放該點陣圖。 - 自動調整像素維度和座標
如要停用預先縮放尺寸和圖片,您可以在資訊清單中將
android:anyDensity
設為"false"
,以程式輔助方式將inScaled
設為"false"
,以程式輔助方式設定Bitmap
。在這種情況下,系統會在繪製時自動調整任何絕對像素座標和像素維度值。這樣做可確保以像素定義的螢幕元素仍能以基準像素密度 (mdpi) 正常顯示的方式顯示大小。系統會對應用程式以透明化的方式處理這項縮放作業,並向應用程式回報經過調整的像素尺寸,而非實體像素尺寸。舉例來說,假設裝置搭載 480x800 的 WVGA 高密度螢幕,大小與傳統 HVGA 螢幕相同,但是正在執行的應用程式已停用預先縮放功能。在此範例中,當系統查詢螢幕尺寸並回報 320x533 (亦即像素密度的近似 mdpi 轉譯) 時,會「符合」應用程式的需求。
接著,當應用程式執行繪圖作業時,例如將 (10,10) 的矩形無效到 (100, 100),系統就會以適當的數量調整座標以轉換座標,但實際上會將區域 (15,15) 失效為 (150、150)。如果應用程式直接操控經過調整的點陣圖,這種差異可能會造成非預期的行為,但為了確保能達到最佳應用程式效能,這種做法屬於合理的取捨。如果您遇到這種情況,請參閱將 dp 單位轉換為像素單位一文。
一般而言,您不會停用預先縮放功能。如要支援多螢幕,最佳做法是遵循本頁說明的基本技巧。
如果應用程式以其他方式操控點陣圖或與螢幕上的像素直接互動,您可能需要採取額外步驟來支援不同的像素密度。舉例來說,如果您透過計算手指交叉的像素數來回應觸控手勢,就必須使用適當的密度獨立像素值,而非實際像素,但您可以在 dp 與 px 值之間進行轉換。
針對所有像素密度進行測試
使用不同的像素密度測試應用程式,確保使用者介面可以正確縮放。請盡可能在實體裝置上測試;如果您無法存取所有不同像素密度的實體裝置,請使用 Android Emulator。
如果您想在實體裝置上測試,但不想購買裝置,可以使用 Firebase Test Lab 存取 Google 資料中心內的裝置。