Flutter for OpenHarmony 家具购买记录App实战:个人中心实现
这篇文章介绍了如何实现一个家具购买记录App的个人中心页面设计。主要内容包括: 页面采用常见的三段式布局:顶部用户信息区、中间统计卡片、底部功能菜单 用户信息区包含圆形头像、昵称和签名,使用棕色渐变背景 统计卡片展示3项核心数据:家具数量(48件)、房间数(6间)、总价值(¥86.5k) 功能菜单分为3组: 家具管理(家具列表、房间管理等4项) 财务管理(购买记录、预算等3项) 其他功能(保修、备
#
个人中心是App的"我的"页面,用户可以在这里查看自己的信息、访问各种功能入口。今天来实现家具购买记录App的个人中心页面,包括用户头像、统计数据、功能菜单三个部分。
做个人中心的时候,我参考了很多App的设计。发现大部分App的个人中心都是顶部放用户信息,中间放统计数据,下面放功能菜单。这种布局用户已经很熟悉了,所以我也采用这种结构。
页面整体结构
个人中心用 StatelessWidget 实现,因为这个页面主要是展示和导航,不需要管理复杂状态。
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '../../app/routes/app_routes.dart';
class ProfilePage extends StatelessWidget {
const ProfilePage({super.key});
导入了四个依赖:Material 组件库、屏幕适配工具、GetX 路由、自定义路由常量。这些是这个页面需要用到的全部依赖。
用 StatelessWidget 而不是 StatefulWidget,是因为这个页面没有需要动态变化的状态。所有数据都是从外部获取的,页面本身只负责展示。
页面主体布局
build 方法里用 SingleChildScrollView 包裹内容,这样内容多了可以滚动。
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFFAF8F5),
body: SingleChildScrollView(
child: Column(
children: [
_buildHeader(),
_buildStatsRow(),
SizedBox(height: 16.h),
注意这个页面没有 AppBar,因为个人中心通常是底部导航的一个 tab,不需要返回按钮。顶部的用户信息区域会延伸到状态栏,形成沉浸式效果。
背景色还是用统一的米白色 0xFFFAF8F5,和其他页面保持一致。
功能菜单分组
功能菜单分成三组:家具管理、财务管理、其他。每组之间用 SizedBox 隔开。
_buildMenuSection('家具管理', [
_buildMenuItem(Icons.chair, '我的家具', () => Get.toNamed(AppRoutes.furnitureList)),
_buildMenuItem(Icons.room, '房间管理', () => Get.toNamed(AppRoutes.roomList)),
_buildMenuItem(Icons.category, '分类管理', () => Get.toNamed(AppRoutes.categoryManage)),
_buildMenuItem(Icons.business, '品牌管理', () => Get.toNamed(AppRoutes.brandManage)),
]),
SizedBox(height: 12.h),
家具管理组包含四个入口:我的家具、房间管理、分类管理、品牌管理。这些都是和家具直接相关的功能。
每个菜单项用 _buildMenuItem 方法构建,传入图标、标题、点击回调。点击后用 GetX 的路由跳转到对应页面。
财务管理分组
财务管理组包含购买记录、预算管理、商家管理三个入口。
_buildMenuSection('财务管理', [
_buildMenuItem(Icons.receipt_long, '购买记录', () => Get.toNamed(AppRoutes.purchaseRecord)),
_buildMenuItem(Icons.account_balance_wallet, '预算管理', () => Get.toNamed(AppRoutes.budgetManage)),
_buildMenuItem(Icons.store, '商家管理', () => Get.toNamed(AppRoutes.storeManage)),
]),
SizedBox(height: 12.h),
这三个功能都和钱相关:购买记录看花了多少钱,预算管理控制花钱上限,商家管理记录在哪买的。
图标选择上,购买记录用收据图标,预算管理用钱包图标,商家管理用商店图标。图标要能直观表达功能含义。
其他功能分组
其他分组放一些辅助功能:保修管理、数据备份、设置、关于我们。
_buildMenuSection('其他', [
_buildMenuItem(Icons.security, '保修管理', () => Get.toNamed(AppRoutes.warrantyManage)),
_buildMenuItem(Icons.cloud_upload, '数据备份', () => Get.toNamed(AppRoutes.dataBackup)),
_buildMenuItem(Icons.settings, '设置', () => Get.toNamed(AppRoutes.settings)),
_buildMenuItem(Icons.info_outline, '关于我们', () => Get.toNamed(AppRoutes.about)),
]),
SizedBox(height: 30.h),
],
),
),
);
}
保修管理虽然也和家具相关,但它更偏向售后服务,所以放在其他分组。数据备份和设置是工具类功能,关于我们是信息展示。
最后加了 30 的底部间距,防止内容贴着屏幕底部,也给底部导航栏留出空间。
顶部用户信息区域
_buildHeader 方法构建顶部的用户信息区域,用渐变背景。
Widget _buildHeader() {
return Container(
padding: EdgeInsets.only(top: 60.h, bottom: 24.h),
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFF8B4513), Color(0xFFA0522D)]
),
),
padding 的 top 设置为 60,是为了避开状态栏。不同设备状态栏高度不一样,60 是一个比较安全的值。
渐变色从深棕色到浅棕色,和 AppBar 的颜色一致,保持整体风格统一。
用户头像和昵称
头像用 CircleAvatar 组件,里面放一个人物图标。昵称和签名用白色文字显示。
child: Column(
children: [
CircleAvatar(
radius: 40.r,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 40.sp, color: const Color(0xFF8B4513)),
),
SizedBox(height: 12.h),
Text('家居达人', style: TextStyle(
color: Colors.white,
fontSize: 20.sp,
fontWeight: FontWeight.bold
)),
SizedBox(height: 4.h),
Text('记录美好家居生活', style: TextStyle(
color: Colors.white70,
fontSize: 13.sp
)),
],
),
);
}
头像半径 40,白色背景,里面的图标用主题棕色。这样头像在渐变背景上很醒目。
昵称"家居达人"用白色加粗显示,是视觉焦点。签名"记录美好家居生活"用半透明白色,作为补充说明。
实际项目中,这些信息应该从用户数据里读取,这里先用固定值展示效果。
统计数据行
_buildStatsRow 方法构建统计数据区域,显示家具数量、房间数、总价值。
Widget _buildStatsRow() {
return Container(
margin: EdgeInsets.all(16.w),
padding: EdgeInsets.all(16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r)
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('48', '家具'),
Container(width: 1, height: 40.h, color: Colors.grey[200]),
_buildStatItem('6', '房间'),
Container(width: 1, height: 40.h, color: Colors.grey[200]),
_buildStatItem('¥86.5k', '总价值'),
],
),
);
}
三个统计项用竖线分隔,竖线用 Container 实现,宽度 1,高度 40,颜色是浅灰色。
白色卡片加圆角,和背景形成对比。margin 和 padding 都是 16,内外间距一致。
spaceAround 让三个统计项均匀分布,竖线自然就在它们中间了。
单个统计项
_buildStatItem 方法构建单个统计项,数值在上,标签在下。
Widget _buildStatItem(String value, String label) {
return Column(
children: [
Text(value, style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: const Color(0xFF8B4513)
)),
SizedBox(height: 4.h),
Text(label, style: TextStyle(
color: Colors.grey[600],
fontSize: 12.sp
)),
]
);
}
数值用主题棕色加粗显示,字号 20,是整个卡片的视觉焦点。标签用灰色小字,起说明作用。
这种上下结构的统计项很常见,用户一眼就能看懂。数值大、标签小,主次分明。
菜单分组容器
_buildMenuSection 方法构建菜单分组的容器,包含标题和菜单项列表。
Widget _buildMenuSection(String title, List<Widget> items) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 16.w),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16.r)
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(16.w),
child: Text(title, style: TextStyle(
fontSize: 14.sp,
fontWeight: FontWeight.bold,
color: const Color(0xFF5D4037)
)),
),
...items,
],
),
);
}
容器只有左右 margin,没有上下 margin,这样多个分组之间的间距由外部的 SizedBox 控制。
标题用深棕色加粗,和设置页面的分组标题样式一致。...items 展开菜单项列表。
白色背景加 16 的圆角,和统计卡片样式统一。整个页面的卡片都用这个样式。
单个菜单项
_buildMenuItem 方法构建单个菜单项,左边图标,中间标题,右边箭头。
Widget _buildMenuItem(IconData icon, String title, VoidCallback onTap) {
return InkWell(
onTap: onTap,
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
child: Row(
children: [
Icon(icon, color: const Color(0xFF8B4513), size: 22.sp),
SizedBox(width: 14.w),
Expanded(child: Text(title, style: TextStyle(fontSize: 14.sp))),
Icon(Icons.chevron_right, color: Colors.grey[400], size: 20.sp),
],
),
),
);
}
}
InkWell 包裹整个区域,点击有水波纹效果。padding 设置水平 16、垂直 14,让点击区域足够大。
图标用主题棕色,大小 22。标题用 Expanded 包裹,占满中间空间。右边箭头用灰色,表示可以点击进入。
这种三段式布局是菜单项的标准样式,用户很熟悉,不需要学习成本。
图标选择原则
给每个菜单项选图标的时候,要考虑图标能不能直观表达功能含义:
我的家具用椅子图标 Icons.chair,直接表示家具。
房间管理用房间图标 Icons.room,表示房间。
分类管理用分类图标 Icons.category,表示分类。
品牌管理用商业图标 Icons.business,表示品牌/公司。
购买记录用收据图标 Icons.receipt_long,表示购买凭证。
预算管理用钱包图标 Icons.account_balance_wallet,表示钱。
商家管理用商店图标 Icons.store,表示商家。
保修管理用安全图标 Icons.security,表示保障。
数据备份用云上传图标 Icons.cloud_upload,表示备份到云端。
设置用齿轮图标 Icons.settings,这是设置的通用图标。
关于我们用信息图标 Icons.info_outline,表示信息说明。
沉浸式状态栏
这个页面没有 AppBar,顶部的渐变区域直接延伸到状态栏。要实现这个效果,需要在 main.dart 里设置状态栏透明。
// 在 main.dart 的 main 函数里添加
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
));
这样状态栏就会变成透明的,渐变背景可以延伸上去。状态栏的图标颜色会自动根据背景调整。
不过要注意,顶部内容要留出状态栏的高度,不然会被状态栏遮挡。这就是为什么 _buildHeader 的 top padding 设置为 60。
数据来源说明
目前页面上的数据都是写死的:48 件家具、6 个房间、86.5k 总价值。实际项目中这些数据应该从数据库查询。
// 示例:从数据库获取统计数据
// final furnitureCount = await db.getFurnitureCount();
// final roomCount = await db.getRoomCount();
// final totalValue = await db.getTotalValue();
可以用 GetX 的控制器来管理这些数据,页面加载时查询数据库,然后更新 UI。
用户昵称和签名也应该从用户信息里读取,如果有登录功能的话。
点击反馈优化
InkWell 的水波纹效果是 Material Design 的标准反馈,但有时候可能想要其他效果。
// 如果想要缩放效果,可以用 GestureDetector 配合 AnimatedScale
// 如果想要高亮效果,可以用 InkWell 的 highlightColor 属性
// 如果想要自定义效果,可以用 GestureDetector 配合自定义动画
目前用默认的水波纹效果就够了,简单而且用户熟悉。
页面跳转方式
所有菜单项点击后都用 Get.toNamed 跳转,这是 GetX 的命名路由跳转方式。
Get.toNamed(AppRoutes.furnitureList)
AppRoutes 是我们定义的路由常量类,里面定义了所有页面的路由路径。用常量而不是字符串,可以避免拼写错误,IDE 也能提供自动补全。
如果需要传参数,可以用 arguments 参数:
Get.toNamed(AppRoutes.furnitureDetail, arguments: {'id': 123})
布局适配要点
这个页面用了很多 flutter_screenutil 的适配方法:
.w 用于宽度相关的值,比如 margin、padding 的水平方向。
.h 用于高度相关的值,比如 padding 的垂直方向、SizedBox 的高度。
.sp 用于字号,会根据系统字体设置缩放。
.r 用于圆角,保持比例协调。
这样在不同尺寸的设备上,页面布局都能保持合理的比例。
小结
个人中心页面的实现主要是布局和导航,把用户信息、统计数据、功能菜单组织在一起。用 StatelessWidget 实现,因为不需要管理复杂状态。
代码组织上,把每个部分抽成独立方法:_buildHeader、_buildStatsRow、_buildMenuSection、_buildMenuItem。这样主 build 方法很清晰,修改某个部分也很方便。
个人中心是用户使用频率很高的页面,所以功能入口的分类和排序很重要。把常用的放前面,相关的放一组,用户找起来就方便。
下一篇会讲关于我们页面的实现,那个页面主要是展示App信息和一些链接入口,敬请期待。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐
所有评论(0)