Flutter for OpenHarmony 家具购买记录App实战:房间详情实现
Flutter房间详情页实现可折叠头部效果,采用CustomScrollView和SliverAppBar组件。页面包含: 可折叠头部显示房间图标和名称 统计卡片展示家具数量和总价值 家具列表展示详细物品信息 悬浮按钮支持快速添加家具 关键实现点: SliverAppBar实现动态折叠效果 FlexibleSpaceBar处理标题和背景过渡 使用房间主题色保持视觉统一 统计卡片采用分隔式布局 悬浮
房间详情页面是从房间列表点进来的,展示这个房间里所有的家具,以及一些统计信息。这个页面用了 CustomScrollView 和 SliverAppBar,实现了一个可折叠的头部效果。
说实话,SliverAppBar 是 Flutter 里比较复杂的组件之一,但效果确实好看。头部展开时显示大图标和房间名,滚动时自动折叠成普通的 AppBar,用户体验很流畅。
页面设计思路
房间详情页面的设计要点:
- 可折叠的头部,展示房间图标和名称
- 统计卡片,显示家具数量和总价值
- 家具列表,展示这个房间里的所有家具
- 悬浮添加按钮,可以快速添加家具到这个房间
头部用房间的主题色作为背景,和房间列表页面的卡片颜色呼应,用户一眼就能认出是哪个房间。
页面基础结构
房间详情页面用 StatelessWidget:
class RoomDetailPage extends StatelessWidget {
const RoomDetailPage({super.key});
在 build 方法里获取路由参数:
Widget build(BuildContext context) {
final room = Get.arguments as Map<String, dynamic>? ?? {
'name': '客厅',
'icon': Icons.weekend,
'count': 12,
'total': 35600.0,
'color': const Color(0xFF8B4513)
};
Get.arguments 获取从房间列表传过来的房间数据。如果没有传参数,就用默认的客厅数据,方便开发调试。
家具列表数据暂时写死:
final furnitures = [
{'name': '北欧实木沙发', 'price': 12800.0, 'date': '2024-01-15'},
{'name': '茶几', 'price': 2800.0, 'date': '2024-01-15'},
{'name': '电视柜', 'price': 3500.0, 'date': '2023-12-20'},
{'name': '落地灯', 'price': 680.0, 'date': '2023-11-10'},
];
实际项目中,这个列表应该根据房间 ID 从数据库查询。
CustomScrollView 结构
页面主体用 CustomScrollView:
return Scaffold(
backgroundColor: const Color(0xFFFAF8F5),
body: CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: 180.h,
pinned: true,
backgroundColor: room['color'] as Color,
foregroundColor: Colors.white,
CustomScrollView 是 Flutter 里用来实现复杂滚动效果的组件,它的子组件必须是 Sliver 系列组件。
SliverAppBar 是可折叠的 AppBar,expandedHeight 设置展开时的高度,pinned: true 表示折叠后 AppBar 会固定在顶部。
背景色用房间的主题色,这样每个房间的详情页颜色都不一样。
FlexibleSpaceBar 实现
SliverAppBar 的 flexibleSpace 参数用来设置可折叠区域的内容:
flexibleSpace: FlexibleSpaceBar(
title: Text(room['name'] as String),
background: Container(
color: (room['color'] as Color).withOpacity(0.2),
child: Center(
child: Icon(
room['icon'] as IconData,
size: 60.sp,
color: Colors.white.withOpacity(0.3)
)
),
),
),
actions: [
IconButton(icon: const Icon(Icons.edit), onPressed: () {})
],
),
FlexibleSpaceBar 的 title 会在折叠过程中自动调整位置和大小,展开时在底部居中,折叠后移到左边变小。
background 是展开时显示的背景内容,这里放了一个大的半透明图标,作为装饰。图标透明度 0.3,不会太抢眼。
右上角有个编辑按钮,点击可以编辑房间信息。
页面内容区域
SliverAppBar 下面是页面的主要内容:
SliverToBoxAdapter(
child: Padding(
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildStatsRow(room),
SizedBox(height: 20.h),
Text('房间家具', style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: const Color(0xFF5D4037)
)),
SizedBox(height: 12.h),
...furnitures.map((f) =>
_buildFurnitureItem(f, room['color'] as Color)
).toList(),
],
),
),
),
],
),
SliverToBoxAdapter 用来把普通的 Widget 转换成 Sliver,这样就能放到 CustomScrollView 里了。
内容包括统计卡片、"房间家具"标题、家具列表。家具列表用展开运算符 ... 把 map 结果展开。
悬浮添加按钮
右下角的添加按钮:
floatingActionButton: FloatingActionButton(
onPressed: () => Get.toNamed(AppRoutes.addFurniture),
backgroundColor: room['color'] as Color,
child: const Icon(Icons.add, color: Colors.white),
),
);
}
按钮颜色用房间的主题色,和页面整体风格统一。点击后跳转到添加家具页面,实际项目中应该带上房间 ID,这样添加的家具会自动关联到这个房间。
统计卡片组件
统计卡片显示家具数量和总价值:
Widget _buildStatsRow(Map<String, dynamic> room) {
return Container(
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('家具数量', '${room['count']}件'),
Container(width: 1, height: 40.h, color: Colors.grey[200]),
_buildStatItem('总价值', '¥${(room['total'] as double).toStringAsFixed(0)}'),
],
),
);
}
卡片里有两个统计项,中间用一条竖线分隔。spaceAround 让两个统计项均匀分布。
竖线用 Container 实现,宽度 1,高度 40,颜色是浅灰色。这种分隔线比用 Divider 更灵活,可以精确控制尺寸。
统计项组件
单个统计项的实现:
Widget _buildStatItem(String label, String value) {
return Column(
children: [
Text(value, style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: const Color(0xFF5D4037)
)),
SizedBox(height: 4.h),
Text(label, style: TextStyle(color: Colors.grey[600], fontSize: 12.sp)),
]
);
}
数值在上面,用大字号加粗显示;标签在下面,用小字号灰色显示。这种上下结构的统计项很常见,信息层次清晰。
家具列表项组件
每个家具是一个卡片:
Widget _buildFurnitureItem(Map<String, dynamic> furniture, Color color) {
return Container(
margin: EdgeInsets.only(bottom: 10.h),
padding: EdgeInsets.all(14.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12.r)
),
child: Row(
children: [
Container(
padding: EdgeInsets.all(10.w),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(10.r)
),
child: Icon(Icons.chair, color: color, size: 24.sp),
),
左边是家具图标,用房间的主题色。这样整个页面的颜色都是统一的,视觉效果很协调。
图标容器的背景色是主题色加 0.1 透明度,和房间列表页面的卡片风格一致。
家具信息和价格
家具名称、日期和价格:
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(furniture['name'] as String, style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 15.sp
)),
Text(furniture['date'] as String, style: TextStyle(
color: Colors.grey[600],
fontSize: 12.sp
)),
]
)
),
Text(
'¥${(furniture['price'] as double).toStringAsFixed(0)}',
style: TextStyle(color: color, fontWeight: FontWeight.bold)
),
],
),
);
}
中间是家具名称和购买日期,用 Expanded 包裹让它占据剩余空间。右边是价格,用房间主题色显示。
价格用 toStringAsFixed(0) 转成整数,不显示小数点。
SliverAppBar 的工作原理
SliverAppBar 的折叠效果是这样实现的:
- 初始状态,AppBar 高度是
expandedHeight,显示完整的flexibleSpace内容 - 用户向上滚动时,AppBar 高度逐渐减小,
flexibleSpace内容逐渐隐藏 - 当高度减小到普通 AppBar 高度时,停止折叠(因为
pinned: true) - 继续滚动时,AppBar 固定在顶部,只显示标题和按钮
FlexibleSpaceBar 的 title 会在这个过程中自动调整位置,从底部居中移动到左边,字号也会变小。这个动画是 Flutter 自动处理的,不需要手动实现。
为什么用 CustomScrollView
普通的 Scaffold + AppBar 没法实现这种折叠效果。CustomScrollView 提供了一个统一的滚动上下文,让 SliverAppBar 和下面的内容能够协调滚动。
CustomScrollView 的子组件必须是 Sliver 系列:
SliverAppBar:可折叠的 AppBarSliverList:列表SliverGrid:网格SliverToBoxAdapter:把普通 Widget 转成 Sliver
这个页面内容不多,用 SliverToBoxAdapter 包一个 Column 就够了。如果家具列表很长,可以改成 SliverList 实现懒加载。
颜色主题的传递
这个页面的颜色主题是从路由参数传过来的,包括:
- AppBar 背景色
- 悬浮按钮颜色
- 家具图标颜色
- 价格文字颜色
所有用到颜色的地方都用 room['color'],这样每个房间的详情页都有自己的主题色,和房间列表页面的卡片颜色一致。
这种设计让用户在不同页面之间切换时,能通过颜色快速识别当前是哪个房间。
小结
房间详情页面用 CustomScrollView + SliverAppBar 实现了可折叠的头部效果。头部展开时显示房间图标和名称,滚动时自动折叠。
页面内容包括统计卡片和家具列表,都用房间的主题色作为点缀,视觉效果统一。悬浮添加按钮方便用户快速添加家具。
下一篇会讲分类管理页面的实现,用列表展示所有家具分类,支持添加和编辑。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐



所有评论(0)