Android 螢幕各種引數的介紹和學習
文章目錄
經常被 Android 裝置紛繁的螢幕搞得是暈頭轉向,下面就梳理一下 Android 中的相關概念。
一、概念
1.1 螢幕大小
螢幕大小是手機對角線的物理尺寸,單位是:英寸(inch),1 inch =2.54 cm(釐米) 。例如現在手機大多都是 “6.0寸” 以上的螢幕,這個就是對角線的尺寸,6.0(inch) X 2.54(cm)/ 1 (inch)= 15.24(cm)
1.2 螢幕解析度
解析度就是手機螢幕的畫素點數,一般描述為:縱畫素 * 橫畫素,如 2240 * 1080,就是在縱方向上有2240個畫素點,在橫方向上有1080個畫素點。
1.3 螢幕畫素密度
螢幕畫素密度(dpi,dots per inch;或 PPI ,pixels per inch),就是每英寸的畫素點,數值越高顯示越細膩。假如一部手機的解析度是 1080*1920 ,螢幕大小是5英寸,那麼此螢幕的密度是多少呢?通過寬1080和高1920,根據勾股定理,得出對角線的畫素大約是2203,那麼用2203/5=440,440dpi就是螢幕的畫素螢幕密度。
1.4 實際密度和系統密度
這裡其實將的還是上面的 螢幕畫素密度
實際密度:就是我們自己算出來的密度,這個密度代表了螢幕真實的細膩程度,如上述例子中的440dpi 就是實際密度,說明這塊螢幕每寸有440個畫素。5英寸1080*1920 的螢幕密度是440,而相同解析度的4.5英寸螢幕是490。如此看來,螢幕密度會出現很多數值,呈現嚴重的碎片化。而密度有時 Android 螢幕將介面進行顯示的依據,那麼 Android 是如何適配這麼多螢幕的呢?其實,每部手機螢幕都有一個初始固定密度,這些數值是120、160、240、320、480,我們權且稱為“系統密度”。大家發現規律沒有?相隔數值之間是2倍的關係。一般情況下,240*320的螢幕是低密度120dpi,即 ldpi
在具體的 Android 專案下,這些表示不同螢幕密度(不同解析度)用來修飾 Android 中 drawable 資料夾以及 value 資料夾,用來區分不同畫素密度下的圖片和 dimen 值,所以在不同 drawable 資料夾下圖片的 densityDpi 的值也是不同的 。這會導致用 BitmapFactory 的 decodeResource建立 Bitmap 時,其載入到記憶體的大小不一樣。(詳見 深入理解Android Bitmap的各種操作)
Google官方指定按照下列標準進行區分:
名稱 | 畫素密度範圍 |
---|---|
mdpi | 120dpi ~ 160dpi |
hdpi | 160dpi ~ 240dpi |
xhdpi | 240dpi ~ 320dpi |
xxhdpi | 320dpi ~ 480dpi |
xxxhdpi | 480dpi ~ 640dpi |
1.5 dp
dp 也可以寫成dip(density independent pixel),即密度無關的畫素。比如,一張寬和高均為100dp的圖片在 320 *480 和480*800的手機上,“看起來”是一樣大,實際上,它們的畫素值並不一樣。dp正是這樣一個尺寸,不管這個螢幕的密度是多少,螢幕上相同dp的大小的元素看起來始終差不多大。另外,文字尺寸使用 sp,即 scale independent pixel 的縮寫,與 dp 類似,是設定字型大小的御用單位。在 Android 中,系統密度為160dpi的中密度手機螢幕為基準螢幕,即320*480的手機螢幕。在這個螢幕中:1dp = 1px。
100dp在320*480(mdpi,160dpi)中是100px。那麼100dp在480*800(hdpi,240dpi)的手機上,根據160與240的比例關係,100dp實際覆蓋了150px。因此,如果你為mdpi手機上提供了一張100px的圖片,這張圖片在hdpi手機上就會拉伸至150px,但是他們都是100dp。要注意一點的就是:dp和px的換算要以系統密度為準,720*1280的系統密度為320,320*480的系統密度為160,320/160=2,那麼在720*1280中,1dp = 2px。同理,在1080*1920中,1dp = 3px。有一個dp和px換算的比例公式:ldpi : mdpi :hdpi:xdpi:xxdpi = 3:4:6:8:12,我們發現相隔數字之間還是2倍的關係。計算的時候,以 mdpi 為基準。如果以 mdpi 為基準比例為:
dpi : mdpi :hdpi:xdpi:xxdpi = 0.75:1:1.5:2:3
二、從系統中獲取相關引數和轉換
2.1 DisplayMetrics
這個類是 Android 提供的記述螢幕有關資訊的一種類,諸如其尺寸、螢幕畫素密度等。
獲取這個物件的方法:
//第一種
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
//第二種
DisplayMetrics metrics=activity.getResources().getDisplayMetrics();
//第三種
Resources.getSystem().getDisplayMetrics();
這個類中有幾個比較重要的屬性:
/**
* The absolute width of the available display size in pixels.
* 裝置的絕對寬度,單位是px
*/
public int widthPixels;
/**
* The absolute height of the available display size in pixels.
* 裝置的絕對高度,單位是px
*/
public int heightPixels;
/**
* The logical density of the display. This is a scaling factor for the
* Density Independent Pixel unit, where one DIP is one pixel on an
* approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
* providing the baseline of the system's display. Thus on a 160dpi screen
* this density value will be 1; on a 120 dpi screen it would be .75; etc.
*
* <p>This value does not exactly follow the real screen size (as given by
* {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
* the overall UI in steps based on gross changes in the display dpi. For
* example, a 240x320 screen will have a density of 1 even if its width is
* 1.8", 1.3", etc. However, if the screen resolution is increased to
* 320x480 but the screen size remained 1.5"x2" then the density would be
* increased (probably to 1.5).
*
* @see #DENSITY_DEFAULT
*簡單來說,可以理解為 density 的數值是 1dp = density px 即 density = dpi/160,也就是在我們介紹從低到高系統密度的比值:
* 0.75 : 1 : 1.5 : 2 : 3
*/
public float density;
/**
* The screen density expressed as dots-per-inch. May be either
* {@link #DENSITY_LOW}, {@link #DENSITY_MEDIUM}, or {@link #DENSITY_HIGH}.
* 就是上面的:螢幕畫素密度(dpi)
*/
public int densityDpi;
/**
* A scaling factor for fonts displayed on the display. This is the same
* as {@link #density}, except that it may be adjusted in smaller
* increments at runtime based on a user preference for the font size.
* 字型顯示的縮放因子,跟上面的 density 是一樣的
*/
public float scaledDensity;
/**
* The exact physical pixels per inch of the screen in the X dimension.
* 水平方向上的dpi
*/
public float xdpi;
/**
* The exact physical pixels per inch of the screen in the Y dimension.
* 豎直方向上的dpi
*/
public float ydpi;
在 DisplayMetrics 中,density 和 densityDpi 這個兩個的線性關係:
density | 1 | 1.5 | 2 | 3 | 3.5 | 4 |
---|---|---|---|---|---|---|
densityDpi | 160 | 240 | 320 | 480 | 560 | 640 |
2.2 TypedValue
TypedValue 是 Android 提供單位轉換的類,這個類是工具類,作為一個動態容器,它存放一些資料值,這些值主要是 resource 中的值。TypedValue 類把對應的值轉化為實際螢幕上的點值,也就是畫素值,總體來說作用:把 Android 系統中的非標準度量尺寸轉變為標準度量尺寸(Android 系統中的標準尺寸是 px,即畫素)。非標準單位:dp 、in、mm、pt、sp
站在巨人的肩膀上:典型應用為:
/**
* Converts an unpacked complex data value holding a dimension to its final floating
* point value. The two parameters <var>unit</var> and <var>value</var>
* are as in {@link #TYPE_DIMENSION}.
*
* @param unit The unit to convert from.
* @param value The value to apply the unit to.
* @param metrics Current display metrics to use in the conversion --
* supplies display density and scaling information.
*
* @return The complex floating point value multiplied by the appropriate
* metrics depending on its unit.
*/
TypedValue.applyDimension(int unit, float value, DisplayMetrics metrics)
其中,第一個引數 unit 是你需要轉換的單位,第二個引數 value 是你需要得到的單位數值,第三個引數 metrics 封裝了螢幕區域各種屬性。
例如:我要得到一個 20dp 在當前裝置上對應的 px 值:
float px_value = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,20,context.getResources().getDisplayMetrics());
還有其他型別:
TypedValue.applyDimension()方法的功能就是把非標準尺寸轉換成標準尺寸:
dp->px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, context.getResources().getDisplayMetrics());
in->px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_IN, 20, context.getResources().getDisplayMetrics());
mm->px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 20, context.getResources().getDisplayMetrics());
pt->px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PT, 20, context.getResources().getDisplayMetrics());
sp->px: TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, context.getResources().getDisplayMetrics());
不積跬步無以至千里,不積小流無以成江海。讓我們默默前行,不蹉跎歲月,不辜負自己。突然想到家園的歌詞:冰雪早已覆蓋我的足跡,遠方的炊煙搖曳溫暖的召喚,風兒無法吹斷我回望的視線,家園好像永遠征途漫漫。是啊,我們人生也是征途漫漫。
站在巨人的肩膀上:
UI設計師不可不知的安卓螢幕知識
Android螢幕適配及DisplayMetrics解析