1. 程式人生 > >android開發:在不同解析度,不同螢幕密度dpi的平板上的字型大小和佈局的自適應

android開發:在不同解析度,不同螢幕密度dpi的平板上的字型大小和佈局的自適應

    最近在這家公司做一些android裝置上的開發,使用了幾款平板進行真機除錯,面對不同解析度,不同螢幕密度dpi的裝置,碰到了一些和虛擬機器不太一樣的情況,在這裡和大家分享一下。

1.一些名詞的簡單理解,後面會有詳細說明

       (1)螢幕尺寸:單位英寸(inch),指的是螢幕對角線長度。

  (2)螢幕密度:單位dpi,指的是每inch上可以顯示多少畫素點即px。

  (3)螢幕解析度:單位px * px,如1280×800,我使用的小米853×480等,指的是一屏顯示多少畫素點。

  (4)螢幕無關畫素:單位dp/dip,指的是自適應螢幕密度的畫素,用於指定控制元件寬高。

  (5)刻度無關畫素:單位sp,指的是自適應字型的畫素,用於指定文字大小。


2.關於螢幕密度dpi

密度可以理解為每英寸包含的畫素個數(單位是dpi),如果螢幕物理密度是160dpi時,dp和px是等效的。

2.1先說下螢幕密度的計算吧

一個手機或者平板,拿到手就可以看到它的尺寸和解析度,我接觸的幾款android裝置有一下幾種:

(1)小米1(最早出的那一款)4寸螢幕,853×480的解析度

(2)聯想ideatab s6000  10.1寸,1280×800

(3)某款android平板,大小引數規格單找不到了,反正是mdpi 800×480

    思路很簡單:由於給了螢幕對角線的長度10.1英寸,再計算對角線上有多少個畫素點,就可以計算每英寸包含的畫素點數。

已(2)為例,看看怎麼計算螢幕密度:√ (1280²+800²

)=1509.43,              1509.43÷10.1=149.449

即其螢幕密度為150dpi。

2.2 android系統對螢幕密度的歸一化處理

如圖,android提供ldpi,mdpi,hdpi,xhdpi,xxhdpi等不同螢幕密度級別,這些都是經過歸一化處理的

ldpi低密度屏,螢幕密度為120dpi, 1dp = 0.75px        (由於畫素點是物理點,所以用2個畫素點來顯示3個dp的內容)

mdpi中密度屏螢幕密度160dpi    1dp = 1px

tvdpi電視密度屏螢幕密度213dpi   1dp = 1.33px

hdpi高密度屏螢幕密度240dpi     1dp = 1.5px

xhdpi極高密度屏螢幕密度320dpi   1dp = 2px

小米1螢幕密度為244dpi,屬於hdpi級別;(2)款平板密度為150dpi,歸一化屬於mdpi級別

這樣就為你的裝置計算好了密度級別,這個很重要

3.屏幕布局layout.xml的適配


3.1不考慮橫豎屏切換

參考自:http://www.cnblogs.com/mybkn/articles/2535519.html    點選開啟連結

作者給了4種方法,我就copy下我借鑑的第一種方法吧:

目前最為推薦的Android多螢幕自適應解決方案。

    該屬性的作用是決定控制元件在其父佈局中的顯示權重,一般用於線性佈局中。其值越小,則對應的layout_width或layout_height的優先順序就越高,一般橫向佈局中,決定的是layout_width的優先順序;縱向佈局中,決定的是layout_height的優先順序。     傳統的layout_weight使用方法是將當前控制元件的layout_widthlayout_height都設定成fill_parent,這樣就可以把控制元件的顯示比例完全交給layout_weight;這樣使用的話,就出現了layout_weight越小,顯示比例越大的情況。不過對於2個控制元件還好,如果控制元件過多,且顯示比例也不相同的時候,控制起來就比較麻煩了,畢竟反比不是那麼好確定的。 於是就有了現在最為流行的0px設值法。看似讓人難以理解的layout_height=0px的寫法,結合layout_weight,卻可以使控制元件成正比例顯示,輕鬆解決了當前Android開發最為頭疼的碎片化問題之一。 先看下面的stylesstyle_layout.xml 複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<resources><!-- 全螢幕拉伸--><style name="layout_full"><item name="android:layout_width">fill_parent</item><item name="android:layout_height">fill_parent</item></style><!-- 固定自身大小--><style name="layout_wrap"><item name="android:layout_width">wrap_content</item><item name="android:layout_height">wrap_content</item></style><!-- 橫向分佈--><style name="layout_horizontal" parent="layout_full"><item name="android:layout_width">0px</item></style><!-- 縱向分佈--><style name="layout_vertical" parent="layout_full"><item name="android:layout_height">0px</item></style></resources>  
複製程式碼 可以看到,layout_widthlayout_height兩個屬性被我封裝成了4style     根據實際佈局情況,選用當中的一種,不需要自己設定,看過我前一個ActivityGroupDemo的同學應該非常熟悉了     然後我的Demo的佈局如下(weight_layout.xml 複製程式碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        style="@style/layout_full"
        android:orientation="vertical"><LinearLayout 
                style="@style/layout_vertical"
                android:layout_weight="1"
                android:orientation="horizontal"><View
                         style="@style/layout_horizontal"
                         android:background="#aa0000"
                         android:layout_weight="1"/><View
                         style="@style/layout_horizontal"
                         android:background="#00aa00"
                         android:layout_weight="4"/><View
                         style="@style/layout_horizontal"
                         android:background="#0000aa"
                         android:layout_weight="3"/><View
                         style="@style/layout_horizontal"
                         android:background="#aaaaaa"
                         android:layout_weight="2"/></LinearLayout><LinearLayout 
                style="@style/layout_vertical"
                android:layout_weight="2"
                android:orientation="vertical"><View
                         style="@style/layout_vertical"
                         android:background="#ffffff"
                         android:layout_weight="4"/><View
                         style="@style/layout_vertical"
                         android:background="#aa0000"
                         android:layout_weight="3"/><View
                         style="@style/layout_vertical"
                         android:background="#00aa00"
                         android:layout_weight="2"/><View
                         style="@style/layout_vertical"
                         android:background="#0000aa"
                         android:layout_weight="1"/></LinearLayout>
</LinearLayout>
複製程式碼

整個介面佈局看起來非常直觀,只是巢狀的邏輯要自己理下。顯示效果如下圖,其中左面一個是480x800的介面,右面的是320x480的介面(後面的圖也如此),可以看出顯示比例和程式碼中完全一致,我就不多說了,大家對照下就能看出來了。


3.2考慮橫豎屏切換

思路是:在res目錄下新建立兩個資料夾:layout-port和layout-land.
把橫屏的xml放到layout-land裡,把豎屏的放到layout-port裡,取一樣的名字。

具體demo木有,boss要求我把螢幕寫成橫屏,寫死了

3.3圖片的適配

準備不同大小的圖片資源,起一樣的名字放在對應的drawable- dpi資料夾下,

      <ImageView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:scaleType="fitCenter"
            android:src="@drawable/xxx"/>

這4個屬性必不可少,簡單的介紹一下,充滿布局,scalType屬性設定為fitCenter保證放大長寬比例,src而不是background

再就是圖示,icon的一些說明:

ldpi (120 dpi)      mdpi (160 dpi)     hdpi (240 dpi)       xhdpi (320 dpi)

36 x 36 px          48 x 48 px            72 x 72 px          96 x 96 px



4.字型大小的適配

思路是如上圖,為不同解析度,不同密度準備一套字型大小的尺寸

在values-xxx-xxx資料夾下建立dimen。xml檔案:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="size_title">20sp</dimen>
    <dimen name="size_name">18sp</dimen>
    <dimen name="size_code">10sp</dimen>
</resources>

有一些我在配置過程中碰到的問題和大家分享一下:

1.資料夾命名:

    如上圖,有些錯誤的資料夾,我的結論是解析度x號前面的數值要比後面的大,不然系統無法識別,

注意:乘號的輸入法,千萬別用漢字輸入法下的x,不然系統無法系別,不要問我為什麼,我是不會告訴你這玩意花了我起碼3個小時才搞明白

2.系統會自動匹配values資料夾

  舉個例子,之前提到的(2)1280x800的,如果你建立values-mdpi-1250x800,values-mdpi-1200x800,(注意了這兩個都不是1280x800的),最後真機聯調的時候,顯示的是比真實解析度小的最大的那套尺寸即values-mdpi-1250x800,而不是1200x800,這點上虛擬機器和真機有很大的區別,xml檢視只會找1280x800的尺寸,如果沒有,他就顯示預設大小的字型。

可以參考下這一篇:點選開啟連結http://www.cnblogs.com/zealotrouge/archive/2012/11/23/2784774.html

3。如果系統系統自動匹配的時候沒有找到最小的尺寸,就會報錯

 所以建議在values下dimen.xml下儲存一份最小的字型尺寸,再難看也好過報錯,是吧

5.字型適配的其他思路

用圖片代替字型,但是EditText有點難搞...


暫時總結的就這麼多了,第一次發原創~~~

爭取以後寫的更好