LayoutBuilder 与自适应布局
学习如何使用 LayoutBuilder widget。
学习如何创建能够适应不同屏幕宽度的布局。
你将完成的内容
步骤
1
简介
简介
现代应用需要在各种尺寸的屏幕上都能良好运行。在本页中,你将学习如何创建能够适应不同屏幕宽度的布局。此应用在大屏幕上显示侧边栏,在小屏幕上使用基于导航的 UI。具体而言,此应用处理两种屏幕尺寸:
-
大屏幕(平板、桌面):并排显示联系人分组和联系人详情。
-
小屏幕(手机):使用导航在联系人分组和详情之间切换。
2
创建联系人分组页面
创建联系人分组页面
首先,为联系人分组屏幕创建 ContactGroupsPage widget 的基本结构。创建 lib/screens/contact_groups.dart 并添加以下基本结构:
import 'package:flutter/cupertino.dart';
class ContactGroupsPage extends StatelessWidget {
const ContactGroupsPage({super.key});
@override
Widget build(BuildContext context) {
return const CupertinoPageScaffold(
backgroundColor: CupertinoColors.extraLightBackgroundGray,
child: Center(child: Text('Contact Groups will go here')),
);
}
}
3
创建联系人页面
创建联系人页面
同样,创建 lib/screens/contacts.dart 以最终显示各个联系人:
import 'package:flutter/cupertino.dart';
class ContactListsPage extends StatelessWidget {
const ContactListsPage({super.key, required this.listId});
final int listId;
@override
Widget build(BuildContext context) {
return const CupertinoPageScaffold(
backgroundColor: CupertinoColors.extraLightBackgroundGray,
child: Center(child: Text('Lists of contacts will go here')),
);
}
}
ContaactsListPage widget 和 ContactGroupsPage widget 是实现自适应布局 widget 所需的占位页面,你将在下一步完成该布局。
4
构建自适应布局基础
构建自适应布局基础
创建 lib/screens/adaptive_layout.dart,并以以下基本结构开始:
import 'package:flutter/cupertino.dart';
import 'contact_groups.dart';
class AdaptiveLayout extends StatefulWidget {
const AdaptiveLayout({super.key});
@override
State<AdaptiveLayout> createState() => _AdaptiveLayoutState();
}
class _AdaptiveLayoutState extends State<AdaptiveLayout> {
@override
Widget build(BuildContext context) {
return const ContactGroupsPage(); // Temporary placeholder
}
}
这是一个 StatefulWidget,因为自适应布局最终需要管理当前选中的联系人分组。
接下来,在 lib/screens/adaptive_layout.dart 中添加屏幕尺寸检测逻辑:
import 'package:flutter/cupertino.dart';
import 'contact_groups.dart';
const largeScreenMinWidth = 600;
class AdaptiveLayout extends StatefulWidget {
const AdaptiveLayout({super.key});
@override
State<AdaptiveLayout> createState() => _AdaptiveLayoutState();
}
class _AdaptiveLayoutState extends State<AdaptiveLayout> {
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final isLargeScreen = constraints.maxWidth > largeScreenMinWidth;
if (isLargeScreen) {
return const Text('Large screen layout'); // Temporary
} else {
return const ContactGroupsPage();
}
},
);
}
}
LayoutBuilder widget 提供有关父级尺寸约束的信息。在 builder 回调中,你会收到一个 BoxConstraints 对象,它会告知你最大可用宽度和高度。
通过检查 constraints.maxWidth > largeScreenMinWidth,你可以决定显示哪种布局。
600 像素的阈值是常用的断点,用于区分手机尺寸屏幕与平板尺寸屏幕。
5
更新主应用
更新主应用
更新 main.dart 以使用自适应布局,这样你就能看到更改效果:
import 'package:flutter/cupertino.dart';
import 'data/contact_group.dart';
import 'screens/adaptive_layout.dart';
final contactGroupsModel = ContactGroupsModel();
void main() {
runApp(const RolodexApp());
}
class RolodexApp extends StatelessWidget {
const RolodexApp({super.key});
@override
Widget build(BuildContext context) {
return const CupertinoApp(
title: 'Rolodex',
theme: CupertinoThemeData(
barBackgroundColor: CupertinoDynamicColor.withBrightness(
color: Color(0xFFF9F9F9),
darkColor: Color(0xFF1D1D1D),
),
),
home: AdaptiveLayout(),
);
}
}
如果你在 Chrome 中运行,可以调整浏览器窗口大小以查看布局变化。
6
添加列表选择功能
添加列表选择功能
大屏幕布局需要跟踪选中的联系人分组。在 lib/screens/adaptive_layout.dart 中使用以下代码更新状态对象:
import 'package:flutter/cupertino.dart';
import 'contact_groups.dart';
const largeScreenMinWidth = 600;
class AdaptiveLayout extends StatefulWidget {
const AdaptiveLayout({super.key});
@override
State<AdaptiveLayout> createState() => _AdaptiveLayoutState();
}
class _AdaptiveLayoutState extends State<AdaptiveLayout> {
int selectedListId = 0;
void _onContactListSelected(int listId) {
setState(() {
selectedListId = listId;
});
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final isLargeScreen = constraints.maxWidth > largeScreenMinWidth;
if (isLargeScreen) {
return const Text('Large screen layout');
} else {
return const ContactGroupsPage();
}
},
);
}
}
selectedListId 变量跟踪当前选中的联系人分组,
_onContactListSelected 在用户做出选择时更新此值。
7
构建大屏幕布局
构建大屏幕布局
现在,在 lib/screens/adaptive_layout.dart 中实现大屏幕的并排布局。首先,将临时文本替换为包含正确布局的 widget。
import 'package:flutter/cupertino.dart';
import 'contact_groups.dart';
const largeScreenMinWidth = 600;
class AdaptiveLayout extends StatefulWidget {
const AdaptiveLayout({super.key});
@override
State<AdaptiveLayout> createState() => _AdaptiveLayoutState();
}
class _AdaptiveLayoutState extends State<AdaptiveLayout> {
int selectedListId = 0;
void _onContactListSelected(int listId) {
setState(() {
selectedListId = listId;
});
}
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final isLargeScreen = constraints.maxWidth > largeScreenMinWidth;
if (isLargeScreen) {
return _buildLargeScreenLayout();
} else {
// For small screens, use the original, navigation-style approach.
return const ContactGroupsPage();
}
},
);
}
Widget _buildLargeScreenLayout() {
return const CupertinoPageScaffold(
backgroundColor: CupertinoColors.extraLightBackgroundGray,
child: SafeArea(child: Row(children: [Text('Sidebar'), Text('Details')])),
);
}
}
大屏幕布局使用 Row 将侧边栏和详情并排放置。
SafeArea 确保内容不会与状态栏等系统 UI 元素重叠。
现在,在 lib/screens/adaptive_layout.dart 中设置两个面板的尺寸并添加视觉分隔线:
Widget _buildLargeScreenLayout() {
return CupertinoPageScaffold(
backgroundColor: CupertinoColors.extraLightBackgroundGray,
child: SafeArea(
child: Row(
children: [
const SizedBox(width: 320, child: Text('Sidebar placeholder')),
Container(width: 1, color: CupertinoColors.separator),
const Expanded(child: Text('Details placeholder')),
],
),
),
);
}
此布局创建以下内容:
用于联系人分组的固定宽度侧边栏(320 像素)。
面板之间的 1 像素分隔线。
-
使用
Expandedwidget 占据剩余空间的详情面板。
8
测试自适应布局
测试自适应布局
热重载应用并测试响应式行为。如果你在 Chrome 中运行,可以调整浏览器窗口大小以查看布局变化:
-
宽窗口 (> 600px):并排显示侧边栏和详情的占位文本。
-
窄窗口 (< 600px):仅显示联系人分组页面。
目前侧边栏和主内容区域都显示占位文本。
在下一课中,你将实现 sliver 以填充联系人列表内容。
9
回顾
回顾
你完成的内容
以下是你本课构建与学习内容的摘要。使用 LayoutBuilder 创建了响应式布局
LayoutBuilder 在其 builder 回调中提供父级的尺寸约束。通过检查 constraints.maxWidth,你可以根据可用空间决定显示哪种布局。
检测屏幕尺寸以选择不同布局
你使用 600 像素断点来区分手机尺寸屏幕与平板尺寸屏幕。这一常用阈值帮助你的应用调整 UI,以便在每种设备上提供最佳体验。
为大屏幕构建了侧边栏与详情布局
在大屏幕上,你使用 Row 并排显示固定宽度侧边栏和 Expanded 详情面板。这一经典模式可以最大化平板和桌面上的屏幕空间。
10
自测
自测
自适应布局测验
1 / 2-
设备的操作系统和屏幕方向。
不正确。
LayoutBuilder 提供尺寸约束,而非操作系统或方向信息。
-
父级的尺寸约束,包括最大宽度和高度。
正确!
LayoutBuilder 的 builder 会收到 BoxConstraints,告知你来自父级的可用空间。
-
当前的主题颜色和排版。
不正确。
主题数据来自 Theme.of(context),而非 LayoutBuilder。
-
widget 树中子 widget 的数量。
不正确。
LayoutBuilder 提供布局约束,而非 widget 树信息。
-
Column
不正确。
Column 垂直排列 widget,而非并排。
-
Row
正确!
Row 水平排列其子级,非常适合将侧边栏和详情面板并排放置。
-
Stack
不正确。
Stack 将 widget 层叠在一起,而非并排。
-
ListView
不正确。
ListView 用于可滚动列表,而非并排布局。
除非另有说明,本文档之所提及适用于 Flutter 3.44.0 版本。本页面最后更新时间:2026-06-18。查看文档源码 或者 为本页面内容提出建议。