1. 程式人生 > >Android中的不同drawable資料夾所帶來的思考

Android中的不同drawable資料夾所帶來的思考

今天模擬手Q的傳送圖片介面做一個toolBar,佈局如下:

    <RelativeLayout
    android:id="@+id/tool_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/photo_select_bottom_bg"
    android:layout_alignParentBottom="true" >

    <Button
        android:id="@+id/preview_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="15dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:text="@string/preview"
        android:textColor="@color/photopreview_btn_text"
        android:textSize="14dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:background="@drawable/photopreview_bottom_left_btn_selector" />

    <Button
        android:id="@+id/magic_stick"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_centerVertical="true"
        android:background="@drawable/pic_icon_edit" />

    <Button
        android:id="@+id/send_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="15dp"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:text="@string/photo_send" 
        android:textColor="@color/photopreview_btn_text"
        android:textSize="14dp"
        android:paddingLeft="15dp"
        android:paddingRight="15dp"
        android:background="@drawable/photo_select_preview_btn" />

</RelativeLayout>

所有的元素都設定了一個backgroundDrawable,但是執行後得出的介面非常奇怪,

仔細檢查了各項設定引數,均正常,無奈之下各種求助google,度娘,終於解決,現記錄筆記如下:

相關知識

  • dip

device independent pixels(裝置獨立畫素),與螢幕密度無關的畫素,這是一個基於螢幕物理的抽象單位。密度可以理解為每英寸所包含的畫素個數,而1dp實際上相當於160dpi(即密度)上的一個點,也就是說,當密度為160時,1dp和1px是等價的。由於android手機的解析度千差萬別,為了讓同一個高度/寬度值在不同解析度的手機上看上去一致,android官方推出了dip的概念。

  • dip和px之間的區別和聯絡

dp和px的轉換公式為px=dip*(density/160)。px就是畫素,打個比方,要畫一條240px的橫線,在480寬的螢幕上看是1半屏款,而在320寬的螢幕上看是2/3(同一個尺寸的螢幕)。而畫一條160dip的橫線,無論在320還是480寬的螢幕上,長度都是一樣的。

  • 關於density

上面給出了dip和px之間的轉化公式,其中涉及到了density,注意,這裡的density並非裝置實際的density,而是歸一化後的density。google將所有的裝置分為四種120(low),160(medium),240(high),320(xhigh)。可以使用getResources().getDisplayMetrics().densityDpi

檢視自己裝置的dpi。依照這四種dpi,android4.0時代,新建android工程,會自動生成drawable,drawalbe-ldpi,drawable-mdpi,drawable-hdpi,drawable-xhdpi五個目錄,系統會根據裝置dpi的大小區相應的資料夾拉取相應的資原始檔。

得出結論

根據上面的知識,終於發現了問題所在,我的手機螢幕解析度是240,因此,圖片檔案應該放在drawable-xhdpi下,但是我卻錯誤的將檔案放在了drawable-mdpi,這裡又涉及到了幾個問題,當資原始檔放在了錯誤的資料夾下,會造成什麼樣的影響呢,這麼多資原始檔夾,系統到底是按照什麼順序來載入呢?通過各種資料查詢加上試驗,終於得出結論如下:

  1. 當圖片資源放在了錯誤的資原始檔夾下時,圖片會根據相應dpi做縮放,拿本例來說,圖片原始大小高度95,當將其放在了drawable-mdpi下時,會通過下列公式計算出大致新的高度95*(240/160) = 142,等於說是在縱向拉伸了圖片,這就是為什麼我們在上圖中看到的元素都大了一號,其實是被背景圖給撐大的。

  2. 載入順序。如果我在drawable-(xdpi,hdpi,mdpi,ldpi)以及drawable這幾個資料夾下放置同一個圖片,那麼系統是按照什麼順序來載入的呢。其實它會先到對應dpi的資料夾下找,找不到就會往比自己高的dpi資料夾下找,然後才會往比自己低的dpi資料夾下找。

至此,問題解決,正常介面: