Android中 dip 和 px 的關系

當我們要在Layout 中定義控件的長寬等維度時,Android的推薦是:

1)所有長寬的單位都定義成dip,除瞭字體的大小

2)字體的大小用sp來表示

這篇文章我們討論一下,為什麼不用像素 px, 而要用dip 表示呢? dip 跟 px 之前的關系是什麼呢?

實踐出真知,代碼來展示。

我們先來定義兩個按鈕,其中一個的寬度是160 dip, 另外一個的寬度是160 px,(註意單位不同)然後來看看在不同的模擬器上有什麼不一樣。


    
     
    
    
    
    
    
    
    
    


同時也定義瞭幾個TextView, 來展示屏幕的寬度,屏幕密度比例 和 屏幕的密度。

public class DipActivity extends Activity{

	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
		float density = displayMetrics.density;
		int densityDpi = displayMetrics.densityDpi;
		int screenWidth = displayMetrics.widthPixels;
		
		setContentView(R.layout.dip_layout);
		
		TextView textViewSw = (TextView)findViewById(R.id.textViewSw);
		textViewSw.setText("screen Width (px):" + screenWidth);
		
		TextView dpView = (TextView)findViewById(R.id.textViewDp);
		dpView.setText("Density :" + density);
		
		TextView pxView = (TextView)findViewById(R.id.textViewPx);
		pxView.setText("Density Dpi : " + String.valueOf(densityDpi));
		
	}
}

然後我們運行代碼,看看效果怎麼樣?如下,上面的是在480*800的模擬器上,下面是在320*480的模擬器上。

我們先來看屏幕為480*800的機器,

Button的寬度為160dip的很明顯要比160px的要長,事實上,160dip的按鈕占據瞭一半的寬度(240px),而160px的Button,就是160px.vcD4KPHA+zqrKssO0u+HV4tH5xNijv8bkyrW+zcrHuPrNvMnP1bnKvrXERGVuc2l0edPQudjBy6OsztKw0cv8s8bOqsPctsixyMD9o6zL/LXEJiMyMDU0MDvKx7Wxx7DGwcS7tcRkcGkgo6hEb3QgUGVyIEluY2gssrvKx2RpcKOpuPogMTYwILXE0ru49rHIwP2hozwvcD4KPHA+1NrGwcS7w9y2yCBEZW5zaXR5IGRwaSDOqjI0MLXEyta7+snPo6zD3LbIscjA/URlbnNpdHkgPSAyNDAgLyAxNjAgPSAxLjUuIDwvcD4KPHA+tvhkaXAguPogcHggtcTWrrzktcSxyMD9INTyzqogcHggPSBkaXAgKiAxLjUsILy0tbHO0sPH1NqyvL7W1tDJ6NbDsLTFpbXEv+3OqjE2MGRpcMqxo6y1scv8vq25/c+1zbO1xLu7y+OjrNW5z9bU2sbBxLvJz7XE0tG+rcrHz/HL2KOstvjG5CYjMjA1NDA7vs3KxzE2MCAqIDEuNSA9IDI0MHB4LjwvcD4KPHA+1NpBbmRyb2lkyta7+tbQo6zSu7Dj09DPwsPmNLj2vLax8LXExsHEu8PctsijrDwvcD4KPHA+MaOpMTIwIC0gTG93ILbU06a1xGRlbnNpdHkgPSAxMjAgLyAxNjAgPSAwLjc1PC9wPgo8cD4yo6kxNjAgLSBNZWRpdW0gttTTprXEZGVuc2l0eSA9IDE2MCAvIDE2MCA9IDEuMCA8L3A+CjxwPjOjqTI0MCAtIEhpZ2ggttTTprXEZGVuc2l0eSA9IDI0MCAvIDE2MCA9IDEuNTwvcD4KPHA+NKOpMzIwIC0gRXh0cmEgSGlnaCC21NOmtcRkZW5zaXR5ID0gMzIwIC8gMTYwID0yLjA8L3A+CjxwPtXiuPYmIzIwNTQwO7/J0tTNqLn9RGlzcGxheU1ldHJpY3PAtMTDtb2jrMjnz8KjujwvcD4KPHA+PC9wPgo8cHJlIGNsYXNzPQ==”brush:java;”>DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
float density = displayMetrics.density;
int densityDpi = displayMetrics.densityDpi;
int screenWidth = displayMetrics.widthPixels;當我們在佈局中以dip為單位的時候,中間其實會經過系統的換算,根據不同的屏幕密度,將其轉換成對應屏幕的像素,從而達到適應不同屏幕分辨率的問題。

在320*480的機器上,可以看到Density Dpi = 160, 那麼其Density = 160/160 = 1.0, 那麼160dip 轉換成像素就是 160 * 1.0 = 160px.

所以160dip的按鈕跟160px的按鈕在屏幕上展現是一樣寬的。

綜合兩個圖來看,當我們定義160dip的時候,無論是在上邊的機器還是下邊的機器,按鈕都是占據屏幕的一半寬度,而如果定義成160px的話,則達不到這樣的效果。

我想這也就是為什麼Android會推薦用dip而不推薦px瞭,因為不同分辨率的手機屏幕實在是太多瞭,用像素的話,定死瞭,真不好看。

而用dip,則系統會去讀取屏幕的密度,再根據密度比例來計算真正要展現在屏幕上的像素,效果會好很多。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *