04_常用容器Widget
Flutter 常用容器 Widget 介绍
Container、Scaffold、Card 等常用容器 Widget 的完整用法。
Container(万能容器)
对应 CSS 中带完整样式属性的 <div>:
Container(
width: 200,
height: 100,
margin: const EdgeInsets.all(16), // 外边距(CSS margin)
padding: const EdgeInsets.symmetric( // 内边距(CSS padding)
horizontal: 20,
vertical: 10,
),
decoration: BoxDecoration(
color: Colors.white, // 背景色
borderRadius: BorderRadius.circular(12), // 圆角(CSS border-radius)
border: Border.all(color: Colors.grey, width: 1), // 边框
boxShadow: [ // 阴影(CSS box-shadow)
BoxShadow(
color: Colors.black.withOpacity(0.1),
blurRadius: 8,
offset: const Offset(0, 4),
),
],
gradient: const LinearGradient( // 渐变背景
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Colors.blue, Colors.purple],
),
image: const DecorationImage( // 背景图
image: NetworkImage('https://example.com/bg.jpg'),
fit: BoxFit.cover,
),
),
child: const Text('内容'),
)
注意:
decoration和color不能同时设置(decoration 里已有 color 属性)。
Scaffold(页面脚手架)
Material Design 页面的标准骨架,提供 AppBar、Drawer、BottomNavigationBar 等插槽:
Scaffold(
// 顶部导航栏
appBar: AppBar(
title: const Text('页面标题'),
leading: IconButton( // 左侧按钮(默认返回键)
icon: const Icon(Icons.menu),
onPressed: () {},
),
actions: [ // 右侧操作按钮
IconButton(icon: const Icon(Icons.search), onPressed: () {}),
IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
],
backgroundColor: Colors.blue,
elevation: 0, // 阴影高度
),
// 主内容区域
body: const Center(child: Text('页面内容')),
// 右下角悬浮按钮(FAB)
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
// 底部导航栏
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
type: BottomNavigationBarType.fixed, // 超 3 项必须设置 fixed
selectedItemColor: Colors.blue,
onTap: (index) {},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
BottomNavigationBarItem(icon: Icon(Icons.search), label: '搜索'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
],
),
// 侧边抽屉
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
const DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Text('用户名', style: TextStyle(color: Colors.white, fontSize: 20)),
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('首页'),
onTap: () {},
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('设置'),
onTap: () {},
),
],
),
),
)
Card(卡片)
Card(
elevation: 4, // 阴影高度
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
margin: const EdgeInsets.all(8),
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('卡片标题', style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 8),
const Text('卡片描述内容,可以是多行文字。'),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(onPressed: () {}, child: const Text('取消')),
const SizedBox(width: 8),
ElevatedButton(onPressed: () {}, child: const Text('确认')),
],
),
],
),
),
)
AppBar 进阶
// 可滚动时折叠的 AppBar(SliverAppBar)
CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 200, // 展开时的高度
pinned: true, // 滚动时固定在顶部
flexibleSpace: FlexibleSpaceBar(
title: const Text('标题'),
background: Image.network(
'https://example.com/banner.jpg',
fit: BoxFit.cover,
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item $index')),
childCount: 30,
),
),
],
)
SnackBar 和 Dialog
// SnackBar(底部提示条,类似 Toast)
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: const Text('操作成功'),
duration: const Duration(seconds: 2),
action: SnackBarAction(
label: '撤销',
onPressed: () {},
),
),
);
// AlertDialog(确认对话框)
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('确认删除'),
content: const Text('此操作不可撤销,确认继续?'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text('取消'),
),
ElevatedButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text('确认'),
),
],
),
);
// BottomSheet(底部弹出面板)
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
),
builder: (context) => Padding(
padding: const EdgeInsets.all(16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(leading: const Icon(Icons.share), title: const Text('分享'), onTap: () {}),
ListTile(leading: const Icon(Icons.copy), title: const Text('复制'), onTap: () {}),
ListTile(leading: const Icon(Icons.delete, color: Colors.red),
title: const Text('删除', style: TextStyle(color: Colors.red)),
onTap: () {}),
],
),
),
);