在这里插入图片描述

猫咪详情页是信息展示的核心,用户点进来能看到这只猫的所有信息。这篇来聊聊如何设计一个信息丰富又不杂乱的详情页。

一、页面接收参数

详情页需要接收猫咪数据:

class CatDetailScreen extends StatelessWidget {
  final CatModel cat;

  const CatDetailScreen({super.key, required this.cat});

required 标记必传参数,编译器会检查。
数据从上一个页面传过来,不需要再从 Provider 读取。

页面结构:


Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(cat.name),
    ),
    body: SingleChildScrollView(
      child: Column(
        children: [
          _buildHeader(context),
          _buildInfoSection(context),
          _buildQuickActions(context),
          _buildHealthSummary(context),
        ],
      ),
    ),
  );
}

AppBar 标题直接用猫咪名字,简洁明了。
四个区块垂直排列,用 SingleChildScrollView 支持滚动。

二、头部渐变区域

头部用渐变背景突出视觉效果:

Widget _buildHeader(BuildContext context) {
  return Container(
    padding: EdgeInsets.all(24.w),
    decoration: BoxDecoration(
      gradient: LinearGradient(
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,
        colors: [Colors.orange, Colors.orange.shade300],
      ),
    ),

LinearGradient 从上到下渐变,颜色由深变浅。
和 AppBar 的橙色衔接自然,视觉上是一体的。

头像居中显示:

child: Column(
  children: [
    CircleAvatar(
      radius: 50.r,
      backgroundColor: Colors.white,
      child: Icon(Icons.pets, size: 50.sp, color: Colors.orange),
    ),

白色背景的头像在橙色渐变上很醒目。
后续可以换成真实照片。

名字和基本信息:

SizedBox(height: 16.h),
Text(
  cat.name,
  style: TextStyle(
    fontSize: 24.sp,
    fontWeight: FontWeight.bold,
    color: Colors.white,
  ),
),

名字用大号粗体,是整个头部的视觉焦点。
白色文字在橙色背景上对比度高。

性别和品种:

Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Icon(
      cat.gender == '公' ? Icons.male : Icons.female,
      color: Colors.white,
      size: 20.sp,
    ),
    SizedBox(width: 8.w),
    Text(
      '${cat.breed} · ${cat.ageString}',
      style: TextStyle(
        fontSize: 16.sp,
        color: Colors.white.withOpacity(0.9),
      ),
    ),
  ],
),

性别图标加品种和年龄,一行展示关键信息。
透明度 0.9 让次要信息稍微弱化。

三、基本信息卡片

信息区用 Card 包裹:

Widget _buildInfoSection(BuildContext context) {
  return Card(
    margin: EdgeInsets.all(16.w),
    child: Padding(
      padding: EdgeInsets.all(16.w),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            '基本信息',
            style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
          ),

Card 自带圆角和阴影,不用额外设置。
标题加粗,和内容区分开。

信息行列表:

SizedBox(height: 16.h),
_buildInfoRow('品种', cat.breed),
_buildInfoRow('性别', cat.gender),
_buildInfoRow('出生日期', DateFormat('yyyy-MM-dd').format(cat.birthDate)),
_buildInfoRow('年龄', cat.ageString),
_buildInfoRow('体重', '${cat.weight} kg'),
_buildInfoRow('绝育状态', cat.isNeutered ? '已绝育' : '未绝育'),

每行一个信息,用统一的组件渲染。
日期用 DateFormat 格式化,更易读。

可选字段条件渲染:

if (cat.microchipId != null && cat.microchipId!.isNotEmpty)
  _buildInfoRow('芯片号', cat.microchipId!),
if (cat.notes != null && cat.notes!.isNotEmpty)
  _buildInfoRow('备注', cat.notes!),

芯片号和备注是选填的,有值才显示。
双重判断:不为 null 且不为空字符串。

四、信息行组件

抽取通用的信息行:

Widget _buildInfoRow(String label, String value) {
  return Padding(
    padding: EdgeInsets.symmetric(vertical: 8.h),
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        SizedBox(
          width: 80.w,
          child: Text(
            label,
            style: TextStyle(color: Colors.grey[600], fontSize: 14.sp),
          ),
        ),

标签固定宽度 80,保证对齐。
crossAxisAlignment.start 让多行文本顶部对齐。

值的展示:

Expanded(
  child: Text(
    value,
    style: TextStyle(fontSize: 14.sp),
  ),
),

Expanded 让值占满剩余空间。
长文本会自动换行,不会溢出。

五、快捷操作区

四个功能入口:

Widget _buildQuickActions(BuildContext context) {
  return Card(
    margin: EdgeInsets.symmetric(horizontal: 16.w),
    child: Padding(
      padding: EdgeInsets.all(16.w),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            '快捷操作',
            style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
          ),

和首页的快捷操作类似,但功能不同。
这里是针对当前猫咪的操作。

操作按钮行:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    _buildActionItem(
      context,
      Icons.restaurant,
      '喂食记录',
      Colors.green,
      () => Navigator.push(context, MaterialPageRoute(
        builder: (_) => FeedingListScreen(catId: cat.id),
      )),
    ),

喂食记录用绿色,和食物相关。
跳转时传入 cat.id,只显示这只猫的记录。

其他操作:

_buildActionItem(
  context,
  Icons.monitor_weight,
  '体重记录',
  Colors.blue,
  () => Navigator.push(context, MaterialPageRoute(
    builder: (_) => WeightChartScreen(catId: cat.id),
  )),
),
_buildActionItem(
  context,
  Icons.timeline,
  '成长记录',
  Colors.purple,
  () => Navigator.push(context, MaterialPageRoute(
    builder: (_) => GrowthMilestoneScreen(cat: cat),
  )),
),
_buildActionItem(
  context,
  Icons.medical_services,
  '健康记录',
  Colors.red,
  () => Navigator.push(context, MaterialPageRoute(
    builder: (_) => HealthRecordListScreen(catId: cat.id),
  )),
),

四种颜色区分四个功能,一目了然。
健康记录用红色,暗示重要性。

六、操作按钮组件

按钮的通用实现:

Widget _buildActionItem(
  BuildContext context,
  IconData icon,
  String label,
  Color color,
  VoidCallback onTap,
) {
  return GestureDetector(
    onTap: onTap,
    child: Column(
      children: [
        Container(
          padding: EdgeInsets.all(12.w),
          decoration: BoxDecoration(
            color: color.withOpacity(0.1),
            borderRadius: BorderRadius.circular(12.r),
          ),
          child: Icon(icon, color: color, size: 28.sp),
        ),

背景用主色的 10% 透明度,淡雅不刺眼。
圆角 12 和其他卡片保持一致。

标签文字:

SizedBox(height: 8.h),
Text(
  label,
  style: TextStyle(fontSize: 12.sp, color: Colors.grey[700]),
),

字号小一点,不抢图标的风头。
灰色文字作为辅助说明。

七、健康概况区

这个区块需要从 HealthProvider 读取数据:

Widget _buildHealthSummary(BuildContext context) {
  return Consumer<HealthProvider>(
    builder: (context, healthProvider, child) {
      final latestVaccination = healthProvider.getLatestVaccination(cat.id);
      final latestDeworming = healthProvider.getLatestDeworming(cat.id);

Consumer 监听健康数据变化。
获取最近一次疫苗和驱虫记录。

卡片结构:

return Card(
  margin: EdgeInsets.all(16.w),
  child: Padding(
    padding: EdgeInsets.all(16.w),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '健康概况',
          style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
        ),

和其他卡片样式统一。
标题用粗体突出。

疫苗信息:

_buildHealthItem(
  '最近疫苗',
  latestVaccination != null
      ? '${latestVaccination.title} (${DateFormat('yyyy-MM-dd').format(latestVaccination.date)})'
      : '暂无记录',
  Icons.vaccines,
  Colors.blue,
),

有记录显示名称和日期,没有显示"暂无记录"。
疫苗用蓝色针管图标。

驱虫信息:

SizedBox(height: 12.h),
_buildHealthItem(
  '最近驱虫',
  latestDeworming != null
      ? '${latestDeworming.title} (${DateFormat('yyyy-MM-dd').format(latestDeworming.date)})'
      : '暂无记录',
  Icons.bug_report,
  Colors.green,
),

驱虫用绿色虫子图标,形象直观。
两条信息之间留 12 的间距。

八、健康项组件

健康信息的通用展示:

Widget _buildHealthItem(String title, String value, IconData icon, Color color) {
  return Row(
    children: [
      Container(
        padding: EdgeInsets.all(8.w),
        decoration: BoxDecoration(
          color: color.withOpacity(0.1),
          borderRadius: BorderRadius.circular(8.r),
        ),
        child: Icon(icon, color: color, size: 20.sp),
      ),

图标放在小方块里,视觉上更整齐。
圆角 8 比操作按钮的 12 小一点,层次分明。

文字部分:

SizedBox(width: 12.w),
Expanded(
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Text(
        title,
        style: TextStyle(fontSize: 12.sp, color: Colors.grey[600]),
      ),
      Text(
        value,
        style: TextStyle(fontSize: 14.sp),
      ),
    ],
  ),
),

标题小字灰色,值正常大小黑色。
上下两行,信息层次清晰。

九、设计思路总结

详情页的设计遵循几个原则:

信息分组:把相关信息放在同一个卡片里,用户扫一眼就能找到想要的。

视觉层次:头部用渐变背景突出,卡片用阴影区分,标题用粗体强调。

操作便捷:常用功能放在快捷操作区,一键直达。

数据联动:健康概况从 Provider 实时读取,数据更新后自动刷新。

小结

详情页是信息展示的集大成者,要在有限的空间里展示尽可能多的信息,同时保持界面整洁。渐变背景、卡片分组、图标配色这些细节都会影响用户体验。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐