无论屏幕尺寸如何,响应式/自适应布局都可以提供经过优化的用户体验。实现响应式/自适应布局,使基于视图的应用支持所有屏幕尺寸、屏幕方向和配置,包括多窗口模式等可调整大小的配置。
自适应设计
如需支持各种设备外形规格,第一步是创建可响应应用可用显示空间量变化的布局。
ConstraintLayout
如需创建自适应布局,最佳方法是使用 ConstraintLayout
作为界面的基本布局。借助 ConstraintLayout
,您可以根据布局中视图之间的空间关系指定每个视图的位置和大小。这样一来,随着显示空间的变化,所有视图可以一起移动和调整大小。
如需使用 ConstraintLayout
构建布局,最简单的方法是使用 Android Studio 中的布局编辑器。借助布局编辑器,您可以将新视图拖动到布局中,应用相对于父视图和同级视图的约束条件,以及设置视图属性,而无需手动修改任何 XML。
![](https://developer.android.google.cn/static/images/screens_support/layout-editor_2x.png?authuser=6&hl=nb)
ConstraintLayout
。
如需了解详情,请参阅使用 ConstraintLayout 构建自适应界面。
自适应宽度和高度
为了确保布局能够适应不同的显示大小,请对视图组件的宽度和高度使用 wrap_content
、match_parent
或 0dp (match constraint)
,而不是硬编码的值:
wrap_content
:视图设置其大小以适应视图包含的内容。match_parent
:视图在父视图中尽可能地展开。0dp (match constraint)
:在ConstraintLayout
中,类似于match_parent
。视图会占用其约束条件内的所有可用空间。
例如:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum" />
图 4 显示了当显示宽度随着设备屏幕方向而发生变化时,TextView
的宽度和高度如何调整。
![](https://developer.android.google.cn/static/images/screens_support/layout-match-parent_2x.png?authuser=6&hl=nb)
TextView
。
TextView
将其宽度设置为填充所有可用空间 (match_parent
),并将其高度设置为所含文本的高度 (wrap_content
) 所需的空间,这使得视图能够适应不同的显示尺寸和不同数量的文本。
如果您使用的是 LinearLayout
,还可以根据布局权重展开子视图,以便这些视图按比例填充可用空间。不过,在嵌套的 LinearLayout
中使用权重将要求系统执行多次布局遍历以确定每个视图的大小,这会降低界面性能。
ConstraintLayout
几乎能够创建 LinearLayout
能够创建的所有布局,而不会影响性能,因此请将嵌套的 LinearLayout
转换为 ConstraintLayout
。然后,您可以使用约束链定义加权布局。
自适应设计
应用的布局应始终能适应不同的显示大小。不过,即使是自适应布局也无法在每台设备或多窗口模式显示屏上提供最佳用户体验。例如,您为手机设计的界面可能无法在平板电脑上提供最佳用户体验。自适应设计可提供针对不同显示屏尺寸进行了优化的备用布局。
对列表-详情界面使用 SlidingPaneLayout
列表-详情界面通常会在不同尺寸的屏幕上提供不同的用户体验。在大屏幕上,列表窗格和详情窗格通常并排显示。选择列表中的某个项后,项信息会显示在详情窗格中,而界面不会更改 - 两个窗格将并排显示。不过,在小屏幕上,两个窗格会分开显示,每个窗格都会占据整个显示区域。选择列表窗格中的某项内容后,详情窗格(包含所选项的信息)会替换列表窗格。返回导航会将详情窗格替换为列表窗格。
SlidingPaneLayout
用于管理用于确定这两种用户体验中的哪一种适合当前窗口大小的逻辑:
<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/item_navigation" />
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
SlidingPaneLayout
中包含的两个视图的 layout_width
和 layout_weight
属性决定了 SlidingPaneLayout
行为。在本例中,如果窗口足够大(至少 580dp 宽)可以同时显示两个视图,则窗格会并排显示。但是,如果窗口宽度小于 580dp,窗格会相互滑动,以分别占据整个应用窗口。
如果窗口宽度大于指定的最小总宽度 (580dp),可以使用 layout_weight
值按比例调整两个窗格的大小。在本例中,列表窗格的宽度始终为 280dp,因为它没有权重。
不过,由于视图的 layout_weight
设置,详情窗格会始终填充 580dp 以外的任何水平空间。
备用布局资源
如需让界面设计适应各种不同的显示屏尺寸,请使用由资源限定符标识的备用布局。
![](https://developer.android.google.cn/static/images/screens_support/sizes-phone-tablet_2x.png?authuser=6&hl=nb)
您可以通过在应用的源代码中创建额外的 res/layout/
目录,提供特定于屏幕的自适应布局。为需要不同布局的每个屏幕配置创建一个目录。然后,将屏幕配置限定符附加到 layout
目录名称(例如,对于可用宽度为 600dp 的屏幕,附加限定符为 layout-w600dp
)。
配置限定符表示应用界面可用的可见显示空间。为应用选择布局时,系统会考虑所有系统装饰(例如导航栏)和窗口配置更改(例如多窗口模式)。
如需在 Android Studio 中创建备用布局,请参阅使用 View 开发界面中的使用布局变体针对不同的屏幕进行优化。
“最小宽度”限定符
通过“最小宽度”屏幕尺寸限定符,您可以为具有最小宽度(以密度无关像素 (dp) 为单位)的显示屏提供备用布局。
通过将屏幕尺寸描述为 dp 的度量值,Android 使您能够创建针对特定显示屏尺寸设计的布局,而无需考虑不同的像素密度。
例如,您可以创建一个名为 main_activity
且针对手机和平板电脑进行了优化的布局,方法是在不同目录中创建该文件的不同版本:
res/layout/main_activity.xml # For phones (smaller than 600dp smallest width) res/layout-sw600dp/main_activity.xml # For 7" tablets (600dp wide or wider)
最小宽度限定符指定显示屏两侧的最小尺寸(不考虑设备当前的屏幕方向),因此可用于指定布局可用的整体显示尺寸。
下面是其他最小宽度值与典型屏幕尺寸的对应关系:
- 320dp:小手机屏幕(240x320 ldpi、320x480 mdpi、480x800 hdpi 等)
- 480dp:约为 5 英寸的大手机屏幕 (480x800 mdpi)
- 600dp:7 英寸平板电脑 (600x1024 mdpi)
- 720dp:10 英寸平板电脑(720x1280 mdpi、800x1280 mdpi 等)
下图更详细地说明了不同屏幕 dp 宽度与不同屏幕尺寸和方向的对应关系。
![](https://developer.android.google.cn/static/images/screens_support/layout-adaptive-breakpoints_2x.png?authuser=6&hl=nb)
“最小宽度”限定符的值为 dp,因为重要的是系统考虑像素密度(而不是原始像素分辨率)之后可用的显示空间量。
您使用资源限定符(例如最小宽度)指定的尺寸不是实际屏幕尺寸,而是指定应用窗口可用的宽度或高度(以 dp 为单位)。Android 系统可能会将部分屏幕用于系统界面(如屏幕底部的系统栏或顶部的状态栏),因此部分屏幕可能不适用于您的布局。如果您的应用在多窗口模式下使用,则该应用只能获取包含该应用的窗口的尺寸信息。调整窗口大小时,它会使用新窗口尺寸触发配置更改,以便系统选择合适的布局文件。因此,您声明的资源限定符尺寸应仅指定应用所需的空间。在为您的布局提供空间时,系统会考虑系统界面使用的所有空间。
“可用宽度”限定符
您可能想要根据可用宽度或高度来更改布局,而不是根据显示屏的最小宽度更改布局。例如,当屏幕宽度至少为 600dp 时,您可能希望使用双窗格布局,但屏幕宽度可能会根据设备的屏幕方向是横向还是纵向而发生变化。在这种情况下,您应该使用“可用宽度”限定符,如下所示:
res/layout/main_activity.xml # For phones (smaller than 600dp available width) res/layout-w600dp/main_activity.xml # For 7" tablets or any screen with 600dp available width # (possibly landscape phones)
如果您的应用需要考虑可用高度,您可以使用“可用高度”限定符。例如,对于屏幕高度至少为 600dp 的屏幕,请使用 layout-h600dp
。
“屏幕方向”限定符
虽然您可能只需组合使用“最小宽度”和“可用宽度”限定符即可支持所有尺寸变化,但您可能还需要改变用户在纵向与横向之间切换时的用户体验。
为此,您可以将 port
或 land
限定符添加到布局目录名称中。只需确保屏幕方向限定符在尺寸限定符后面即可。例如:
res/layout/main_activity.xml # For phones res/layout-land/main_activity.xml # For phones in landscape res/layout-sw600dp/main_activity.xml # For 7" tablets res/layout-sw600dp-land/main_activity.xml # For 7" tablets in landscape
如需详细了解所有屏幕配置限定符,请参阅应用资源概览。
窗口大小类别
窗口大小类别是视口断点,可帮助您创建自适应布局。这些断点会将您的应用可用的显示区域标识为“较小”“中”或“展开”。宽度和高度是单独指定的,因此应用始终具有宽度的窗口大小类别和高度的窗口大小类别。
如需以程序化方式应用自适应布局,请执行以下操作:
- 根据窗口大小类别断点创建布局资源
- 使用 Jetpack WindowManager 库中的
WindowSizeClass#compute()
函数计算应用的宽度和高度窗口大小类别 - 针对当前窗口大小类别膨胀布局资源
如需了解详情,请参阅窗口大小类别。
使用 fragment 将界面组件模块化
在针对多种显示尺寸设计应用时,请使用 fragment 将界面逻辑提取到单独的组件中,以确保不会在 activity 之间不必要地重复界面行为。然后,您可以组合 fragment 以在大屏幕上创建多窗格布局,或者将 fragment 放置在小屏幕上的单独 activity 中。
例如,您可以使用一个包含列表的 fragment 和另一个包含列表项详情的 fragment,以实现“列表-详情”模式(请参阅上文的 SlidingPaneLayout)。在大屏幕上,fragment 可以并排显示;在小屏幕上,则会分别填满屏幕。
如需了解详情,请参阅 fragment 概览。
activity 嵌入
如果应用由多个 activity 组成,activity 嵌入可让您轻松创建自适应界面。
activity 嵌入会在应用的任务窗口中同时显示多个 activity 或同一 activity 的多个实例。在大屏幕上,activity 可以并排显示;在小屏幕上,activity 会相互堆叠。
您可以通过创建 XML 配置文件来确定应用如何显示其 activity,系统会使用该文件根据显示屏大小确定适当的呈现方式。或者,您也可以进行 Jetpack WindowManager API 调用。
activity 嵌入支持设备屏幕方向的变化和可折叠设备,以及在设备旋转或折叠和展开时堆叠和取消堆叠 activity。
如需了解详情,请参阅 activity 嵌入。
屏幕尺寸和宽高比
针对各种屏幕尺寸和宽高比测试应用,以确保界面正确缩放。
Android 10(API 级别 29)及更高版本支持各种宽高比。可折叠设备的外形规格各不相同,从高窄型屏幕(如折叠时为 21:9)到方形宽高比(展开时为 1:1)不等。
为确保与尽可能多的设备兼容,请尽可能多地针对以下屏幕宽高比测试您的应用:
![](https://developer.android.google.cn/static/images/guide/topics/ui/foldables/fold-screen-ratios.png?authuser=6&hl=nb)
如果您无法访问具有要测试的所有不同屏幕尺寸的设备,则可以使用 Android 模拟器模拟几乎任何屏幕尺寸。
如果您希望在真实设备上进行测试,但没有设备,则可以使用 Firebase Test Lab 访问 Google 数据中心的设备。
其他资源
- Material Design - 了解布局