[轉]Android中dp,px,sp概念梳理以及如何做到螢幕適配

來源:互聯網
上載者:User

標籤:

http://blog.csdn.net/jiangwei0910410003/article/details/40509571

 

今天又開始我的App開發,因為之前一直做的是SDK,所以涉及到介面UI很少,剛開始做Android應用的時候,沒有對dp,px,sp等概念有一個深入的瞭解,只知道他們之間的轉化,還有寫個轉換工具類等。做Android已經有一年多了,現在再次開始App開發,決定沒遇到一個概念,必須得弄透徹。好吧,下面進入主題吧:

 

首先來看一下他們的基本概念:

px   :是螢幕的像素點
dp   :一個基於density的抽象單位,如果一個160dpi的螢幕,1dp=1px
dip  :等同於dp
sp   :同dp相似,但還會根據使用者的字型大小偏好來縮放(建議使用sp作為文本的單位,其它用dip)

 

通過上面的知識我們可以看到這裡只要弄懂px和dp之間的關係就可以了。那麼下面重點來看一下他們兩之間的關係:

針對dip和px 的關係,做以下概述:

1). px (pixels)像素 :

一個像素通常被視為映像的最小的完整採樣,這個用的比較多,特別是web開發,頁面基本都是使用像素作為單位的.

2). dip或dp (device independent pixels):

裝置獨立像素 — 這個和裝置硬體有關,一般我們為了支援手機上多種解析度,如WVGA、HVGA

和QVGA,都會使用dip作為長度的單位

下面來看一下手機螢幕類型和密度以及解析度的對應關係

QVGA屏density=120         QVGA(240*320)
HVGA屏density=160         HVGA(320*480)
WVGA屏density=240        WVGA(480*800)
WQVGA屏density=120      WQVGA(240*400)

 

註:density值表示每英寸有多少個顯示點,與解析度是兩個概念。

 

不同density下螢幕解析度資訊是不同的,以480dip*800dip的 WVGA(density=240)為例

1、當density=120時 

轉化:轉化係數=120/240

螢幕實際解析度為240px*400px (兩個點對應一個解析度)

狀態列和標題列高各19px或者25dip

橫屏是螢幕寬度400px 或者800dip,工作區域高度211px或者480dip

豎屏時螢幕寬度240px或者480dip,工作區域高度381px或者775dip

2、當density=160時 

轉化:轉化係數=160/240

螢幕實際解析度為320px*533px (3個點對應兩個解析度)

狀態列和標題列高個25px或者25dip

橫屏是螢幕寬度533px 或者800dip,工作區域高度295px或者480dip

豎屏時螢幕寬度320px或者480dip,工作區域高度508px或者775dip

3、當density=240時 

轉化:轉化係數=240/240

螢幕實際解析度為480px*800px (一個點對於一個解析度)

狀態列和標題列高個38px或者25dip

橫屏是螢幕寬度800px 或者800dip,工作區域高度442px或者480dip

豎屏時螢幕寬度480px或者480dip,工作區域高度762px或者775dip

我們一般在項目中會定義多個適配資源檔夾(values-XXX,drawable-XXX等)

drawable-ldpi:     螢幕密度為120的手機裝置

drawable-mdpi:   螢幕密度為160的手機裝置(此為baseline,其他均以此為基準,在此裝置上,1dp = 1px)

drawable-hdpi:    螢幕密度為240的手機裝置

drawable-xhdpi:  螢幕密度為320的手機裝置

drawable-xxhdpi:螢幕密度為480的手機裝置

(values也是一樣,當然還有一點要注意:values和values-hdpi效果是一樣的,drawable和drawable-hdpi效果也是一樣的,所以一般我們都會在這兩個檔案夾中存放的值是一樣的,如果兩個都有的話,適配更好)


apk的資源套件中

當螢幕density=240時,使用hdpi 標籤的資源

當螢幕density=160時,使用mdpi標籤的資源

當螢幕density=120時,使用ldpi標籤的資源

當螢幕density=320時,使用xhdpi標籤的資源

當螢幕density=480時,使用xxhdpi標籤的資源

不加任何標籤的資源是各種解析度情況下共用的

所以布局時盡量使用單位dip,少使用px

dp與px換算公式:
pixs =dips * (densityDpi/160). 
dips=(pixs*160)/densityDpi

但是我們在代碼裡面進行轉化的時候還需要有一個位移值:0.5f

 

[java] view plaincopy 
  1. private static final float scale = mContext.getResources().getDisplayMetrics().density;  
  2.   
  3. private static final float scaledDensity = mContext.mContext.getResources().getDisplayMetrics().scaledDensity;  
  4.   
  5. /** 
  6.  * dp轉成px 
  7.  * @param dipValue 
  8.  * @return 
  9.  */  
  10. public static int dip2px(float dipValue) {  
  11.     return (int) (dipValue * scale + 0.5f);  
  12. }  
  13.   
  14. /** 
  15.  * px轉成dp 
  16.  * @param pxValue 
  17.  * @return 
  18.  */  
  19. public static int px2dip(float pxValue) {  
  20.     return (int) (pxValue / scale + 0.5f);  
  21. }  
  22.   
  23. /** 
  24.  * sp轉成px 
  25.  * @param spValue 
  26.  * @param type 
  27.  * @return 
  28.  */  
  29. public static float sp2px(float spValue, int type) {  
  30.     switch (type) {  
  31.     case CHINESE:  
  32.         return spValue * scaledDensity;  
  33.     case NUMBER_OR_CHARACTER:  
  34.         return spValue * scaledDensity * 10.0f / 18.0f;  
  35.     default:  
  36.         return spValue * scaledDensity;  
  37.     }  
  38. }  

 

我們看到,這裡的scale是在這個類DisplayMetrics中定義的全域變數,其實這個值就是當前手機的density/160,scaleDensity是用來px和sp之間的轉化和scale差不多。還有一點就是這裡轉化都會有一個位移值處理

dp這個單位可能對web開發的人比較陌生,因為一般都是使用px(像素)
但是,現在在開始android應用和遊戲後,基本上都轉換成用dp作用為單位了,因為可以支援多種解析度的手機.

 

上面看到了px和dp之間的關係以及轉化,下面在來看一下使用情境吧,就是為什麼我們會使用到他們之間的轉化,我們在xml中一般定義大小都是使用dp為單位的,但是有時候我們需要在代碼裡面設定一些間距和位置:

下面的代碼

[java] view plaincopy 
  1. android.view.ViewGroup.LayoutParams.height  
  2. android.view.ViewGroup.LayoutParams.width  


上面這兩個屬性的單位為像素,但是為了相容多種解析度的手機,我們需要最好使用dip,時候我們可以調用以下的代碼進行轉換.

[java] view plaincopy 
  1. int heightPx= DisplayUtil.dip2px(this, 33);  
  2. mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = heightPx;  

 

當然我們有時候也會在代碼中擷取values檔案夾中的demen.xml檔案中的值,代碼如下:

 

[java] view plaincopy 
  1. float height = this.getResources().getDimension(R.dimen.height);  
  2. txt.height = px2dip((int)height);//將height轉化成px  

 

不知道他擷取的就是dimens.xml檔案中定義的dp值,所以這裡還手動的進行了轉化操作,但是發現顯示的效果和我們預期不一樣,然後就把值列印了一下看,盡然是兩倍,就是通過getDimension方法擷取到的值是dimen.xml檔案中定義的值的兩倍,這不科學呀,然後就search一下了,發現有三個類似的方法,

getDimension

getDimensionPixelOffset

getDimensionPixelSize

他們的功能都是不一樣的:

通過一個例子來看看他們的區別:

dimen.xml:

 

[html] view plaincopy 
  1. <dimen name="activity_vertical_margin1">16dp</dimen>    
  2. <dimen name="activity_vertical_margin2">16px</dimen>    
  3. <dimen name="activity_vertical_margin3">16sp</dimen>   

 

代碼:

 

[java] view plaincopy 
  1. float a1=getResources().getDimension(R.dimen.activity_vertical_margin1);    
  2. int a2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin1);    
  3. int a3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin1);    
  4.   
  5. float b1=getResources().getDimension(R.dimen.activity_vertical_margin2);    
  6. int b2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin2);    
  7. int b3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);    
  8.   
  9. float c1=getResources().getDimension(R.dimen.activity_vertical_margin3);    
  10. int c2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin3);    
  11. int c3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3);    
  12.   
  13. Log.i("test", "getDimension= "+a1+", getDimensionPixelOffset="+a2+",getDimensionPixelSize="+a3);    
  14. Log.i("test", "getDimension= "+b1+", getDimensionPixelOffset="+b2+",getDimensionPixelSize="+b3);    
  15. Log.i("test", "getDimension= "+c1+", getDimensionPixelOffset="+c2+",getDimensionPixelSize="+c3);      

 

 

對於裝置1(1280*720,160dpi,density=1.0):

列印結果:

對於裝置2(480*800,240dpi,density=1.5):

列印結果:

 

可見getDimension和getDimensionPixelOffset的功能差不多,都是擷取某個dimen的值,如果是dp或sp的單位,將其乘以density,如果是px,則不乘;兩個函數的區別是一個返回float,一個返回int.
getDimensionPixelSize則不管寫的是dp還是sp還是px,都會乘以denstiy.

所以我們在使用getDimension方法擷取到的值的時候就不需要進行轉化了~~

 

下面是我在工作中進行螢幕適配的小工具:http://download.csdn.net/detail/jiangwei0910410003/8144585

是一個小Demo,運行之後,就可以得到這個裝置擷取資源的檔案夾了,然後我們就可以在指定的檔案夾中定義它的尺寸即可。

 

總結:dp和px的相關知識就介紹到這裡了,這個只是很容易混淆的,而且在面試和筆試的時候都會遇到,所以這些概念還是弄清楚比較好啦~~

(PS:其實寫完了,我還是不太記得住~~)

 

[轉]Android中dp,px,sp概念梳理以及如何做到螢幕適配

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.