前言
怎么能让程序根据设备分辨率或屏幕大小的不同来动态加载布局呢?
虽然动态添加 Fragment
的功能很强大,但也只是在一个布局文件中添加或替换 Fragment
。要实现以上需求,就要用到 Android 的 资源限定符(Resource Qualifiers) 机制了,它能让我们在不同设备上提供不同的布局。
使用最小宽度限定符
在过去,你可能会使用 large
或 xlarge
等限定符来区分设备,但因其定义太过模糊,所以早已不被官方推荐使用了。目前推荐使用最小宽度限定符(sw<N>dp
)来区分设备。
其中 sw
是 Smallest-width 的缩写,表示设备屏幕最短边的宽度值,单位为 dp
。它可以让我们给屏幕的宽度指定一个最小值,屏幕宽度大于等于这个值的设备就加载一套布局,小于这个值的设备就加载另一套布局。
注意:这个值并不会随着屏幕旋转而改变,这是一个固定值。
实战
来到之前的 FragmentTest
项目中,我们的目标是:在手机上就会显示新闻标题列表,在平板上,左侧区域显示新闻标题列表,右侧区域显示新闻详情。
项目在这篇博客中:Fragment 入门教程:从核心概念到实践操作
在默认的 res/layout/activity_main.xml
布局文件中:
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/leftFrag"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
只保留左侧的 Fragment
容器,并且让它充满父布局的可用空间,这个布局用于手机。
然后,在 res
目录下新建 layout-sw600dp
文件夹,当设备的最小宽度大于等于 600dp 时,会加载这个文件夹下的布局。在该文件夹下新建一个布局文件,也叫 activity_main.xml
,代码如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/leftFrag"
android:name="com.example.fragmenttest.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/rightFrag"
android:name="com.example.fragmenttest.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3" />
</LinearLayout>
这个布局用于平板。在程序运行时,在平板上,系统会自动加载 layout-sw600dp/activity_main
布局,而在手机上,会自动加载 layout/activity_main
布局。
运行效果
在平板上的运行效果:
在手机上的运行效果:
这样,我们就借助了最小宽度限定符实现了程序在运行时动态加载布局的功能。
常见限定符
常见的限定符如下表所示:
屏幕特征 | 限定符 | 描述 |
---|---|---|
最小宽度 | sw<N>dp |
屏幕最短边的 dp 值,不随方向改变。 |
可用宽度 | w<N>dp |
当前可用的宽度的 dp 值,会随方向改变。 |
可用高度 | h<N>dp |
当前可用的高度的 dp 值,会随方向改变。 |
方向 | land , port |
横屏或竖屏。 |
屏幕密度 | ldpi , mdpi , hdpi , xhdpi , xxhdpi |
每英寸像素点的数量。 |
其中最小宽度可用于区分手机/平板设备的动态布局。方向可提供特定方向下的布局。而屏幕密度主要用于 Drawable 图片资源的适配,确保图片清晰度,很少用于动态布局。