雖然動態添加碎片的功能很強大,可以解決很多實際開發中的問題,但是它畢竟只是在 一個布局文件中進行一些添加和替換操作。如果程序能夠根據設備的分辨率或屏幕大小在運 行時來決定加載哪個布局,那我們可發揮的空間就更多了。因此本節我們就來探討一下 Android 中動態加載布局的技巧。
4.4.1 使用限定符
如果你經常使用平板電腦,應該會發現很多的平板應用現在都采用的是雙頁模式(程序 會在左側的面板上顯示一個包含子項的列表,在右側的面板上顯示內容),因為平板電腦的 屏幕足夠大,完全可以同時顯示下兩頁的內容,但手機的屏幕一次就只能顯示一頁的內容,因此兩個頁面需要分開顯示。
那么怎樣才能在運行時判斷程序應該是使用雙頁模式還是單頁模式呢?這就需要借助 限定符(Qualifiers)來實現了。我們通過一個例子來學習一下它的用法,修改 FragmentTest 項目中的 activity_main.xml 文件,代碼如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >
<fragment android:id="@+id/left_fragment" android:name="com.example.fragmenttest.LeftFragment" android:layout_width="match_parent" android:layout_height="match_parent" />
</LinearLayout>
這里將多余的代碼都刪掉,只留下一個左側碎片,並讓它充滿整個父布局。接着在 res 目錄下新建 layout-large 文件夾,在這個文件夾下新建一個布局,也叫做 activity_main.xml, 代碼如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >
<fragment android:id="@+id/left_fragment" android:name="com.example.fragmenttest.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" />
<fragment android:id="@+id/right_fragment" android:name="com.example.fragmenttest.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" />
</LinearLayout>
可以看到,layout/activity_main 布局只包含了一個碎片,即單頁模式,而 layout-large/
activity_main 布局包含了兩個碎片,即雙頁模式。其中 large 就是一個限定符,那些屏幕被認 為是 large 的設備就會自動加載 layout-large 文件夾下的布局,而小屏幕的設備則還是會加載 layout 文件夾下的布局。
然后將 MainActivity 中按鈕點擊事件的代碼屏蔽掉,並在平板模擬器上重新運行程序, 效果如圖 4.13 所示。

圖 4.13
再啟動一個手機模擬器,並在這個模擬器上重新運行程序,效果如圖 4.14 所示。

圖 4.14
這樣我們就實現了在程序運行時動態加載布局的功能。
Android 中一些常見的限定符可以參考下表。
| 屏幕特征 |
限定符 |
描述 |
|
大小 |
small |
提供給小屏幕設備的資源 |
| normal |
提供給中等屏幕設備的資源 |
|
| large |
提供給大屏幕設備的資源 |
|
| xlarge |
提供給超大屏幕設備的資源 |
|
|
分辨率 |
ldpi |
提供給低分辨率設備的資源(120dpi 以下) |
| mdpi |
提供給中等分辨率設備的資源(120dpi 到 160dpi) |
|
| hdpi |
提供給高分辨率設備的資源(160dpi 到 240dpi) |
|
| xhdpi |
提供給超高分辨率設備的資源(240dpi 到 320dpi) |
|
|
方向 |
land |
提供給橫屏設備的資源 |
| port |
提供給豎屏設備的資源 |
4.4.2 使用最小寬度限定符
在上一小節中我們使用 large 限定符成功解決了單頁雙頁的判斷問題,不過很快又有一 個新的問題出現了,large 到底是指多大呢?有的時候我們希望可以更加靈活地為不同設備加 載布 局,不 管它們 是不是 被系統 認定為 “ large ”,這 時就可 以使用 最小寬 度限定 符
(Smallest-width Qualifier)了。
最小寬度限定符允許我們對屏幕的寬度指定一個最小指(以 dp 為單位),然后以這個最 小值為臨界點,屏幕寬度大於這個值的設備就加載一個布局,屏幕寬度小於這個值的設備就 加載另一個布局。
在 res 目錄下新建 layout-sw600dp 文件夾,然后在這個文件夾下新建 activity_main.xml
布局,代碼如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" >
<fragment android:id="@+id/left_fragment" android:name="com.example.fragmenttest.LeftFragment" android:layout_width="0dp" android:layout_height="match_parent"
android:layout_weight="1" />
<fragment android:id="@+id/right_fragment" android:name="com.example.fragmenttest.RightFragment" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" />
</LinearLayout>
這就意味着,當程序運行在屏幕寬度大於 600dp 的設備上時,會加載 layout-sw600dp/ activity_main 布局,當程序運行在屏幕寬度小於 600dp 的設備上時,則仍然加載默認的 layout/activity_main 布局。
需要注意一點,最小寬度限定符是在 Android 3.2 版本引入的,由於這里我們最低兼容 的系統版本是 4.0,所以可以放心地使用它。
