編輯:關於Android編程
今天又開始我的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
private static final float scale = mContext.getResources().getDisplayMetrics().density; private static final float scaledDensity = mContext.mContext.getResources().getDisplayMetrics().scaledDensity; /** * dp轉成px * @param dipValue * @return */ public static int dip2px(float dipValue) { return (int) (dipValue * scale + 0.5f); } /** * px轉成dp * @param pxValue * @return */ public static int px2dip(float pxValue) { return (int) (pxValue / scale + 0.5f); } /** * sp轉成px * @param spValue * @param type * @return */ public static float sp2px(float spValue, int type) { switch (type) { case CHINESE: return spValue * scaledDensity; case NUMBER_OR_CHARACTER: return spValue * scaledDensity * 10.0f / 18.0f; default: return spValue * scaledDensity; } }
我們看到,這裡的scale是在這個類DisplayMetrics中定義的全局變量,其實這個值就是當前手機的density/160,scaleDensity是用來px和sp之間的轉化和scale差不多。還有一點就是這裡轉化都會有一個偏移值處理
dp這個單位可能對web開發的人比較陌生,因為一般都是使用px(像素)
但是,現在在開始android應用和游戲後,基本上都轉換成用dp作用為單位了,因為可以支持多種分辨率的手機.
上面看到了px和dp之間的關系以及轉化,下面在來看一下使用場景吧,就是為什麼我們會使用到他們之間的轉化,我們在xml中一般定義大小都是使用dp為單位的,但是有時候我們需要在代碼裡面設置一些間距和位置:
下面的代碼
android.view.ViewGroup.LayoutParams.height android.view.ViewGroup.LayoutParams.width
int heightPx= DisplayUtil.dip2px(this, 33); mTabHost.getTabWidget().getChildAt(i).getLayoutParams().height = heightPx;
float height = this.getResources().getDimension(R.dimen.height); txt.height = px2dip((int)height);//將height轉化成px
不知道他獲取的就是dimens.xml文件中定義的dp值,所以這裡還手動的進行了轉化操作,但是發現顯示的效果和我們預期不一樣,然後就把值打印了一下看,盡然是兩倍,就是通過getDimension方法獲取到的值是dimen.xml文件中定義的值的兩倍,這不科學呀,然後就search一下了,發現有三個類似的方法,
getDimension
getDimensionPixelOffset
getDimensionPixelSize
他們的功能都是不一樣的:
通過一個例子來看看他們的區別:
dimen.xml:
16dp 16px 16sp
代碼:
float a1=getResources().getDimension(R.dimen.activity_vertical_margin1); int a2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin1); int a3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin1); float b1=getResources().getDimension(R.dimen.activity_vertical_margin2); int b2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin2); int b3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3); float c1=getResources().getDimension(R.dimen.activity_vertical_margin3); int c2=getResources().getDimensionPixelOffset(R.dimen.activity_vertical_margin3); int c3=getResources().getDimensionPixelSize(R.dimen.activity_vertical_margin3); Log.i("test", "getDimension= "+a1+", getDimensionPixelOffset="+a2+",getDimensionPixelSize="+a3); Log.i("test", "getDimension= "+b1+", getDimensionPixelOffset="+b2+",getDimensionPixelSize="+b3); Log.i("test", "getDimension= "+c1+", getDimensionPixelOffset="+c2+",getDimensionPixelSize="+c3);
對於設備1(1280*720,160dpi,density=1.0):
對於設備2(480*800,240dpi,density=1.5):
打印結果:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD48cD48aW1nIHNyYz0="/uploadfile/Collfiles/20141028/2014102809110571.png" alt="" />
可見getDimension和getDimensionPixelOffset的功能差不多,都是獲取某個dimen的值,如果是dp或sp的單位,將其乘以density,如果是px,則不乘;兩個函數的區別是一個返回float,一個返回int.
getDimensionPixelSize則不管寫的是dp還是sp還是px,都會乘以denstiy.
所以我們在使用getDimension方法獲取到的值的時候就不需要進行轉化了~~
總結:dp和px的相關知識就介紹到這裡了,這個只是很容易混淆的,而且在面試和筆試的時候都會遇到,所以這些概念還是弄清楚比較好啦~~
(PS:其實寫完了,我還是不太記得住~~)
孩放假,在家沒事,所以把手機丟給他玩,沒想到他自己琢磨,竟然設置了密碼。各種試,各種問,都沒解開。實在不想清空數據,因為裡面記了很多賬,還有不少重要的短消息
一.MVP理論簡介1.為何要在android中引入MVP??在Android項目中,Activity和Fragment占據了大部分的開發工作。而MVP設計模式可以優化Ac
ctrl+shift+N 查找文件,以懸浮窗口的形式搜索 contrl+N 查找類,與ctrl+shift+N相似,但是只能查找類 ctrl + E 最近打開的文件,可
本文實例講述了Android中Market的Loading效果實現方法。分享給大家供大家參考。具體如下:在Android中,要實現Loading效果,一般情況下都使用Pr