天天看點

關于動态擷取設定像素大小以及TypedValue.applyDimension()的使用

大多數情況下,我們要考慮手機的适配問題,以前做項目的時候,都是以480為标準,現在手機越來越發達,都以720為标準(大多數)進行螢幕适配.進行适配的話,免不了用dimens檔案,在檔案中存儲需要用到的值,然後根據不同的手機設定不同的檔案夾,這是比較通用的解決方案,當然,這肯定不是唯一的.在dp能解決大多數的适配問題的時候,一些局部的适配我們通常是在代碼裡設定,根據不同的螢幕密度,擷取不同的像素值來設定.

擷取像素值的方法,一般我們是寫一個工具類,将要設定的dp轉成不同的px來進行适配.

例如這樣:

<span style="white-space:pre">	</span>/**
	 * 擷取螢幕密度
	 * 
	 * @return float
	 * @throws
	 */
	public static float getDensity(Context context) {
		DisplayMetrics dm = new DisplayMetrics();
		dm = context.getResources().getDisplayMetrics();
		return dm.density;
	}

	/**
	 * dp轉px
	 * 
	 * @param dpValue
	 *            dp
	 * @return int px
	 * @throws
	 */
	public static int dp2px(Context context, float dpValue) {
		return (int) (dpValue * getDensity(context) + 0.5f);
	}
           

這樣就能比較友善的設定控件的位置,并且做到适配的目的.

但是,Android本身是不是已經有方法幫助我們轉化了,貌似大多數人都沒有考慮過.這就是接下來要說的TypedValue這個類.

先看一段demo代碼:

<span style="white-space:pre">	</span>public class MainActivity extends Activity {

	<span style="white-space:pre">	</span>@Override
	<span style="white-space:pre">	</span>protected void onCreate(Bundle savedInstanceState) {
		<span style="white-space:pre">	</span>super.onCreate(savedInstanceState);
		<span style="white-space:pre">	</span>setContentView(R.layout.activity_main);
		<span style="white-space:pre">	</span>TextView tView = (TextView) findViewById(R.id.dimen);
		<span style="white-space:pre">	</span>float dimension = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, this.getResources().getDisplayMetrics());
		<span style="white-space:pre">	</span>tView.setText("dimen : "+dimension);
	<span style="white-space:pre">	</span>}
	<span style="white-space:pre">	</span>/**
	<span style="white-space:pre">	</span> * 當機關是dp時,320*480上的值是5.0,720*1280是的值是10.0
	<span style="white-space:pre">	</span> * 當機關是sp時,320*480上的值是5.0,720*1280是的值是10.0
	<span style="white-space:pre">	</span> * 當機關是px時,320*480上的值是5.0,720*1280是的值是5.0
	<span style="white-space:pre">	</span> * 
	<span style="white-space:pre">	</span> * 以此總結,此函數方法可通過不同的像素密度将不同的值根據機關不同全部轉化成該裝置的px值.
	<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>}
           

看注釋的内容是不是發現了,沒錯,這個就是Android提供給我們的轉化成不同px的方法.

<span style="white-space:pre">	</span>TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, this.getResources().getDisplayMetrics());<span style="font-family: Arial, Helvetica, sans-serif;">裡,第一個參數是你的機關,這裡寫的是DIP,同樣注釋裡寫的是執行後的結果,我們發現通過這個方法,5dp就被轉化成不同的px了.</span>
           

現在我們點進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;
    }
           

一目了然!

這就是Android給我們做的通過不同的硬體來轉換不同的px.可以看到,dip是跟density有關的,而sp是跟縮放比例有關的.其他的如PI,IN,MM則是跟xdpi有關,那麼xdpi是什麼東東,我們繼續看下源碼:

<span style="white-space:pre">	public void setToDefaults() {
        widthPixels = 0;
        heightPixels = 0;
        density = DENSITY_DEVICE / (float) DENSITY_DEFAULT;
        densityDpi = DENSITY_DEVICE;
        scaledDensity = density;
        xdpi = DENSITY_DEVICE;
        ydpi = DENSITY_DEVICE;
        noncompatWidthPixels = 0;
        noncompatHeightPixels = 0;
    }</span>
           

不難找到這些代碼,我們發現設定xdpi和density的初始值的時候,他們的差別在于density多除了一個default的值.是以xdpi同樣是跟硬體的density息息相關.

知道了這些,以後在代碼裡就不用自己寫dp2px這類的轉化工具了.

有問題請留言,多多指正.謝謝~~

轉載請注明出處,尊重下勞動成果,嘿嘿~~