无论屏幕大小如何,自适应布局都能提供经过优化的用户体验。实现响应式/自适应布局,让基于 View 的应用支持所有显示大小、屏幕方向和配置,包括可调整大小的配置(例如多窗口模式)。
自适应设计
如需支持各种设备外形规格,第一步就是制作一个能够灵活应对应用可用的显示空间量变化的布局。
ConstraintLayout
如需制作自适应布局,最好的方法是将 ConstraintLayout
用作界面的基本布局。使用 ConstraintLayout
,您可以根据布局中视图之间的空间关系指定每个视图的位置和大小。当显示空间发生变化时,所有视图都可以随之移动和调整大小。
如需使用 ConstraintLayout
构建布局,最简单的方法是使用 Android Studio 中的布局编辑器。借助布局编辑器,您可以将新视图拖动到布局中,应用与父视图和同级视图相关的约束条件,以及设置视图的属性,完全不必手动编辑任何 XML。
![](https://developer.android.com/static/images/screens_support/layout-editor_2x.png?authuser=5&hl=zh-cn)
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.com/static/images/screens_support/layout-match-parent_2x.png?authuser=5&hl=zh-cn)
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.com/static/images/screens_support/sizes-phone-tablet_2x.png?authuser=5&hl=zh-cn)
您可以通过在应用的源代码中创建额外的 res/layout/
目录,提供特定于屏幕的布局。针对需要不同布局的每种屏幕配置创建一个目录。然后,将屏幕配置限定符附加到 layout
目录名称(例如,对于可用宽度为 600dp 的屏幕,附加限定符为 layout-w600dp
)。
这些配置限定符表示应用界面可用的可见显示空间。为应用选择布局时,系统会考虑所有系统装饰(例如导航栏)和窗口配置更改(例如多窗口模式)。
如需在 Android Studio 中创建备用布局,请参阅使用 View 开发界面中的使用布局变体针对不同屏幕进行优化。
“最小宽度”限定符
您可以使用“最小宽度”屏幕尺寸限定符,为具有以密度无关像素 (dp) 衡量的最小宽度的显示屏提供备用布局。
在 Android 平台上,您可以用 dp 为度量单位来描述屏幕尺寸,从而针对具体的显示屏尺寸创建专用布局,而不必担心像素密度的变化。
例如,您可以创建一个名为 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.com/static/images/screens_support/layout-adaptive-breakpoints_2x.png?authuser=5&hl=zh-cn)
“最小宽度”限定符的数值是密度无关像素,因为重要的是系统考虑像素密度(而不是原始像素分辨率)之后可用的显示空间量。
您使用“最小宽度”等资源限定符指定的尺寸不是实际屏幕尺寸。相反,这类尺寸指定了应用窗口可用的宽度或高度(以 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 将界面组件模块化
在针对多种显示屏尺寸设计应用时,如需确保不会在 activity 之间不必要地重复界面行为,可以使用 fragment 将界面逻辑提取到单独的组件中。然后,您可以组合 fragment 以制作适用于大屏设备的多窗格布局,或者将 fragment 放置在适用于小屏设备的单独 activity 中。
例如,您可以使用一个包含列表的 fragment 和另一个包含列表项详情的 fragment,以实现列表-详情模式(请参阅上文的 SlidingPaneLayout)。在大屏幕上,fragment 可以并排显示;在小屏幕上,则会分别填满屏幕。
如需了解详情,请参阅 fragment 概览。
activity 嵌入
如果您的应用由多个 activity 组成,activity 嵌入可让您轻松制作自适应界面。
借助 activity 嵌入,系统可在一个应用的任务窗口中同时显示多个 activity 或同一 activity 的多个实例。在大屏幕上,activity 可以并排显示;在小屏幕上,则会相互堆叠显示。
您可通过创建 XML 配置文件来确定应用如何显示其 activity,系统会利用该 XML 配置文件来确定适合显示大小的呈现方式。或者,您也可以进行 Jetpack WindowManager API 调用。
activity 嵌入支持设备屏幕方向变化和可折叠设备,该功能会随着设备旋转或折叠/展开而堆叠和取消堆叠 activity。
如需了解详情,请参阅 activity 嵌入。
屏幕尺寸和宽高比
您可以针对各种屏幕尺寸和宽高比测试您的应用,以确保界面正确缩放。
Android 10(API 级别 29)及更高版本支持各种宽高比。可折叠设备的外形规格丰富,从窄长的屏幕(如折叠时的长宽比为 21:9)到方形的屏幕(展开时的宽高比为 1:1),多种多样。
为确保与尽可能多的设备兼容,请尽可能多地针对以下屏幕宽高比来测试您的应用:
![](https://developer.android.com/static/images/guide/topics/ui/foldables/fold-screen-ratios.png?authuser=5&hl=zh-cn)
如果您身边没有具有各种不同屏幕尺寸的实体设备可供测试,则可以使用 Android 模拟器模拟任何屏幕尺寸。
如果您还是希望在真实设备上进行测试,但没有设备,则可以使用 Firebase Test Lab 访问 Google 数据中心内的设备。
其他资源
- Material Design - 了解布局