Android屏幕適配問題,dip,px,dpi,ppi,sp,density,分辨率,尺寸詳細解釋及轉換


一.概念解釋

1.dip:

dip也簡稱dp,官方的解釋是device independent pixels:設備無關像素,意思是在不同分辨率,尺寸的設備上的效果是一樣的,待會會解釋原因

2.px:

px即pixel的縮寫,在我們手機上呈現的一條線,一個面,一張圖像都是由最小的單位像素來表示的,如下圖

3.分辨率:

分辨率的單位是px,表示一個設備在橫縱方向上的像素點的數量,例如很多手機的像素是1920×1080px,注意看這里的單位就是px

4.屏幕尺寸:

常見的屏幕尺寸有5.5,6單位是英寸(inch),表示的是手機的對角線的長度

5.ppi:

每英寸所擁有的像素點的數量(pixels per inch),可以根據勾股定理求出對角線的像素數量,然后除以尺寸

6.dpi:

(Dot Per Inch)每英寸所擁有的物理點數量,可以看成人為的把一個手機的物理尺寸分成每英寸多少個點。

7.sp:

(Scaled Pixels)與密度和字體縮放度無關的像素,與dp類似,但是可以根據用戶的字體大小首選項進行縮放

8.metrics.density:

從字面上的意思來說是“密度”,不過它不等於像素密度,也不等於dpi

提供手機屏幕配置圖片一張,對照以上學習

二.關系以及轉換

什么叫密度?

Android 中的密度就是屏幕每英
寸所包含的像素數,通常以 dpi為單位。比如一個手機屏幕的寬是 2 英寸長是 3 英寸,如果
它的分辨率是 320*480 像素,那這個屏幕的密度就是 160dpi,如果它的分辨率是 640*960,
那這個屏幕的密度就是 320dpi,因此密度值越高的屏幕顯示的效果就越精細

1.dpi和ppi的關系

dpi是物理上的,即人為的划分每英寸上面有多少個點,但是這個物理點到底多長,需要多少個像素點去填這個並不固定,ppi是圖像上的,即每英寸有多少個像素點


注意在android中dpi所指的概念就是圖像上的ppi

dpi最早是用於印刷行業,跟ppi還是有本質不同的,Android應該是誤用了dpi這個概念。但是在android中我們認為dpi就等於ppi就可以了

谷歌把160ppi的屏幕規定有160dpi,即一個物理點對應一個像素點,所以現在160這個值是固定的了

二.px和dp的轉換

metrics.density = dpi/160

這其中dpi和160的單位都是(像素/英寸),所以metrics.density根本沒有單位只是一個比值,用來描述dp和px的關系,

1px = metrics.density * 1dp

說到這里,sp和px的關系也就不用解釋了,和dp與px的關系類似

三.實例

1.textView.setTextSize()這個方法默認接收的值的單位sp

按住ctrl+左鍵點擊方法就可以進入看源碼了,進去后我們發現它調用了一個重載方法,多了個參數TypedValue.COMPLEX_UNIT_SP

public void setTextSize(float size) {
setTextSize(TypedValue.COMPLEX_UNIT_SP, size);
}

然后再點進去看

public void setTextSize(int unit, float size) {
Context c = getContext();
Resources r;

if (c == null)
r = Resources.getSystem();
else
r = c.getResources();

setRawTextSize(TypedValue.applyDimension(
unit, size, r.getDisplayMetrics()));
}

最終調用的是applyDimension這個方法,我們再看

public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}

這個方法中unit是單位的意思,用來表明你傳入的是什么單位的值,針對unit的取值做了不同的事,以unit值為COMPLEX_UNIT_SP為例,最終返回的是value * metrics.scaledDensity,這里的metrics.scaledDensity就是之前說過的metrics.density,px和sp的比值,所以這個方法內部最終把我們傳入的sp轉換成了px,這就說明了真正渲染圖片所用的尺寸單位還是px,sp和dp只是個方便使用的虛擬單位

2.以LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(int width, int height)為例,所有的Params構造需要傳入的寬高參數單位都是px,為了屏幕適配的更好,這里需要我們在傳入之前把它轉換為dp,為了四舍五入,在實際手動轉換當中的公式是px = dp×density +0.5f× (dp>=0?1:-1)


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com