Responsive Design — 一种构建界面的方法,布局会自动适应设备的尺寸、方向和类型。在移动开发中,responsive design 通过 iOS 中的 size classes 和 Android 中的 configuration qualifiers 实现。本文讨论了自适应布局的原理、两个平台的工具和代码示例。
要点
Responsive Design — 一种构建界面的方法,布局对屏幕尺寸、方向和可用空间做出反应,在不损失功能的情况下重新排列元素的位置。该术语由 Ethan Marcotte 于 2010 年为网页设计提出,但原理完全适用于原生移动应用程序。
在移动开发中,responsive design 意味着同一个应用程序在所有设备上都能正确显示:从 iPhone SE (375 pt) 到 iPad Pro (1024 pt 竖屏),从 Android 智能手机 (360 dp) 到平板电脑 (800 dp)。关键元素包括 灵活网格 (flexible grid)、自适应图片 和框架级别的 media queries (size classes, qualifiers)。
根据 Apple Developer Documentation,应用程序应该是通用的 — 在所有设备上运行,无需为 iPad 单独编译。Google Play 推荐通过 Jetpack WindowManager 和 canonical layouts 使用 adaptive layouts。缺乏对平板电脑的适配是负面评价的常见原因。
Responsive 和 adaptive 这两个术语经常混淆,尽管它们描述的是不同的方法。Responsive design 使用灵活网格,不断适应屏幕宽度。Adaptive design 为预定义的 breakpoints 使用固定布局 — 应用程序在这些布局之间跳转。
| 特征 | Responsive Design | Adaptive Design |
|---|---|---|
| 方法 | 连续流动 | 离散切换 |
| 网格 | 百分比,流体 | 每个 breakpoint 固定 |
| 实现 | Auto Layout, Flexbox, ConstraintLayout | Size Classes, layout-w600dp, 单独的 storyboard |
| 设计布局数量 | 一个,但灵活 | 多个(phone portrait, phone landscape, tablet) |
在实践中,移动应用程序结合使用两种方法。基础网格以 responsive 方式构建(Auto Layout 带有约束依赖),当达到 breakpoint(例如宽度 > 600 pt)时,布局切换到具有不同元素组合的自适应版本。iOS 结合了 Auto Layout (responsive) 和 Size Classes (adaptive)。Android 结合了 ConstraintLayout (responsive) 和 qualifier 资源 (adaptive)。
Size Classes — iOS 机制,将可用屏幕空间按两个轴分类:水平和垂直。每个轴可以是 Compact (C) 或 Regular (R)。组合提供四种布局适应变体:CR(普通 iPhone 竖屏)、RR(iPad 竖屏/横屏)、RC(iPhone 横屏 Plus/Pro Max)、CC(iPad Split View)。
// 在 Swift 中定义 Size Classes
import UIKit
class AdaptiveViewController: UIViewController {
override func traitCollectionDidChange(
_ previousTraitCollection: UITraitCollection?
) {
super.traitCollectionDidChange(previousTraitCollection)
adjustLayout(for: traitCollection)
}
private func adjustLayout(for traits: UITraitCollection) {
switch (traits.horizontalSizeClass, traits.verticalSizeClass) {
case (.regular, .regular):
showSplitView() // iPad — 显示 master-detail
case (.compact, .regular):
showStackedView() // iPhone 竖屏 — 堆栈布局
case (.compact, .compact):
showCompactView() // iPhone SE 横屏 — 最小化
default:
showDefaultView()
}
}
private func showSplitView() {
// 我们使用 UISplitViewController 或 HStack
}
private func showStackedView() {
// iPhone 的垂直堆栈
}
private func showCompactView() {
// 隐藏次要元素,显示主要元素
}
}在 Interface Builder 中,Size Classes 通过 “wAny hAny” 面板配置 — 开发人员选择特定组合(wRegular hRegular, wCompact hRegular)并添加约束变体。SwiftUI 使用 @Environment(\.horizontalSizeClass) 和 @Environment(\.verticalSizeClass) 进行响应式适配 — 当方向或窗口大小改变时,SwiftUI 自动重新绘制视图。
// SwiftUI 中的 Size Classes
import SwiftUI
struct ResponsiveView: View {
@Environment(\.horizontalSizeClass) private var hSizeClass
var body: some View {
if hSizeClass == .regular {
// iPad — 带侧面板的水平布局
HStack {
SidebarView()
.frame(width: 300)
ContentView()
}
} else {
// iPhone — 全屏垂直堆栈
VStack {
ContentView()
}
}
}
}Configuration Qualifiers — Android 机制,根据设备特性加载不同资源(layout, values, drawables)。限定符包括屏幕尺寸(small, normal, large, xlarge)、方向(port, land)、最小宽度(sw
// 在 Kotlin 中定义设备配置
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val config = resources.configuration
val screenWidthDp = config.screenWidthDp
val screenHeightDp = config.screenHeightDp
val orientation = config.orientation
when {
screenWidthDp >= 900 -> setContentView(R.layout.activity_main_tablet)
screenWidthDp >= 600 -> setContentView(R.layout.activity_main_sw600)
else -> setContentView(R.layout.activity_main_phone)
}
}
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
supportFragmentManager.beginTransaction()
.replace(R.id.container, LandscapeFragment())
.commit()
}
}
}不同屏幕的资源结构:res/layout/activity_main.xml(手机)、res/layout-sw600dp/activity_main.xml(7 英寸平板)、res/layout-sw720dp/activity_main.xml(10 英寸平板)。Android 根据 smallestWidth 自动选择正确的布局 — 屏幕在 dp 中的最小宽度,与方向无关。sw
// Jetpack Compose — 用于适配的 WindowSizeClass
@Composable
fun ResponsiveScreen() {
val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
when {
windowSizeClass.windowSizeClass == WindowWidthSizeClass.EXPANDED -> {
TabletLayout() // >= 840 dp
}
windowSizeClass.windowSizeClass == WindowWidthSizeClass.MEDIUM -> {
MediumLayout() // 600–840 dp
}
else -> {
CompactLayout() // < 600 dp
}
}
}Jetpack WindowManager(androidx.window 库)提供具有三种宽度类别的 WindowSizeClass:COMPACT (0–600 dp)、MEDIUM (600–840 dp)、EXPANDED (>840 dp)。这是旧版 qualifier 文件夹的现代替代方案。Google 推荐用于适配可折叠设备和平板电脑。
自适应网格是 responsive design 的基础。元素使用百分比比例、灵活约束和 intrinsic content size 而不是固定尺寸。Breakpoints — 屏幕宽度的点,当达到这些点时布局在状态之间切换。
| Breakpoint | iOS Size Class | Android Qualifier | 设备类型 |
|---|---|---|---|
| 0–374 pt / dp | Compact width | — | iPhone SE, 旧版 Android |
| 375–599 pt / dp | Compact width | sw320dp | iPhone 14, Galaxy S24 |
| 600–839 pt / dp | Regular width | sw600dp | iPad mini, 7 英寸平板 |
| 840+ pt / dp | Regular width | sw720dp | iPad Pro, 10 英寸平板 |
Google Material Design 和 Apple HIG 推荐的 breakpoints:0–599 dp(手机,一列)、600–839 dp(平板,两列,navigation rail)、840+ dp(平板,三列,navigation drawer)。Breakpoints 数量不应超过 4 个 — 过多的过渡点会增加维护和测试的复杂性。
成功的 responsive design 需要遵守过去十年来 iOS 和 Android 开发者社区制定的一套规则。以下是基于 Apple HIG、Google Material Design 和实际项目经验的关键建议。
自适应设计的主要原则:内容决定布局,而不是相反。如果在 iPad 上显示与 iPhone 相同的卡片堆叠,只是横向拉伸 — 这不是 responsive design。Responsive design 重新构思了组合:iPhone 上 — 垂直滚动,iPad 上 — 带侧面板的 master-detail。
常见问题
Responsive Design 使用灵活网格,逐渐适应屏幕宽度。Adaptive Layout 在 breakpoint 点处切换固定布局。在实践中,两种方法结合使用:responsive 基础网格 + 用于重大更改(手机 vs 平板)的自适应切换。
iOS 使用两个轴:水平(Compact/Regular)和垂直(Compact/Regular)。竖屏 iPhone — Compact width, Regular height (CR)。iPad — Regular width, Regular height (RR)。横屏 iPhone Plus/Pro Max — Regular width, Compact height (RC)。开发人员为每种组合设置约束变体。
sw600dp (smallestWidth 600 dp) — Android 资源限定符,表示设备的最小屏幕宽度至少为 600 dp。用于为平板电脑(7 英寸及以上)加载替代布局。方向不影响 — sw 考虑屏幕的最小边。
在 iOS 上使用具有不同 Size Classes 的模拟器和 SwiftUI 中具有不同尺寸设备的 Preview。在 Android 上 — 模拟器中的设备配置文件(Pixel 5, Pixel C, Galaxy Tab)和 Android Studio 中的 Layout Validation。在两个平台上务必在实体 iPad/Android 平板和可折叠设备上进行测试。
Canonical layouts — Google Material Design 3 提供的现成自适应组合模式:list-detail(列表 + 详情)、feed(卡片流)、supporting pane(主要内容 + 操作面板)。每种模式有三个变体(compact/medium/expanded)并自动适应 WindowSizeClass。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。