在这里插入图片描述

个人中心是用户管理个人信息和访问各项功能的入口页面。这篇文章带大家实现个人中心模块,包括用户信息展示、统计数据和功能菜单。

页面整体设计

个人中心页面分为三个主要区域:顶部用户信息区、中间统计卡片、底部功能菜单列表。

页面采用StatelessWidget实现:

class ProfilePage extends StatelessWidget {
  const ProfilePage({super.key});

页面不需要维护内部状态,所有数据从Provider获取。
const构造函数可以让Flutter复用Widget实例。

导入依赖包

在文件开头导入必要的依赖:

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

material.dart提供Material Design风格的组件。
provider用于状态管理和数据共享。

导入项目内部文件:

import '../../providers/app_provider.dart';
import 'edit_profile_page.dart';
import 'settings_page.dart';
import '../club/my_clubs_page.dart';
import '../activity/my_activities_page.dart';

这些是个人中心会跳转到的各个子页面。
使用相对路径引入,保持代码结构清晰。

构建页面骨架

使用Scaffold搭建基本结构:

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('我的'),
        actions: [
          IconButton(
            icon: const Icon(Icons.settings),
            onPressed: () => Navigator.push(
              context, 
              MaterialPageRoute(
                builder: (_) => const SettingsPage()
              )
            ),
          ),
        ],
      ),

AppBar右侧放置设置按钮,点击进入设置页面。
标题简洁地显示"我的",符合常见的Tab命名习惯。

监听数据变化

页面主体使用Consumer监听数据:

      body: Consumer<AppProvider>(
        builder: (context, provider, _) {
          final user = provider.currentUser;
          return SingleChildScrollView(
            child: Column(
              children: [
                _buildUserHeader(context, user, provider),
                const SizedBox(height: 16),
                _buildStatsCard(provider),
                const SizedBox(height: 16),
                _buildMenuSection(context),
              ],
            ),
          );
        },
      ),
    );
  }

Consumer自动订阅AppProvider的变化。
SingleChildScrollView让内容超出屏幕时可以滚动。

页面分为三个区块,用SizedBox分隔。
每个区块由独立的方法构建,代码结构清晰。

用户信息头部

构建用户信息展示区域:

  Widget _buildUserHeader(
    BuildContext context, 
    user, 
    AppProvider provider
  ) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: const BoxDecoration(
        gradient: LinearGradient(
          colors: [Color(0xFF4A90E2), Color(0xFF357ABD)],
          begin: Alignment.topCenter,
          end: Alignment.bottomCenter,
        ),
      ),

Container作为头部区域的容器。
LinearGradient创建从上到下的蓝色渐变背景。

渐变背景让页面更有层次感。
蓝色系和整体风格保持一致。

用户头像和基本信息

头部内容使用Row横向布局:

      child: Column(
        children: [
          Row(
            children: [
              CircleAvatar(
                radius: 40,
                backgroundColor: Colors.white,
                child: Text(
                  user.name[0], 
                  style: const TextStyle(
                    fontSize: 32, 
                    color: Color(0xFF4A90E2), 
                    fontWeight: FontWeight.bold
                  )
                ),
              ),
              const SizedBox(width: 16),

CircleAvatar显示用户名首字母作为头像。
白色背景在蓝色渐变上很醒目。

radius设为40像素,直径80像素大小适中。
首字母头像是没有真实图片时的常用方案。

用户详细信息

显示用户姓名、学号、学院专业:

              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      user.name, 
                      style: const TextStyle(
                        color: Colors.white, 
                        fontSize: 22, 
                        fontWeight: FontWeight.bold
                      )
                    ),
                    const SizedBox(height: 4),
                    Text(
                      user.studentId, 
                      style: const TextStyle(
                        color: Colors.white70, 
                        fontSize: 14
                      )
                    ),

用户名用白色粗体22像素字号突出显示。
学号用白色70%透明度,作为次要信息。

学院和专业信息:

                    const SizedBox(height: 4),
                    Text(
                      '${user.college}  ${user.major}', 
                      style: const TextStyle(
                        color: Colors.white70, 
                        fontSize: 13
                      )
                    ),
                  ],
                ),
              ),

学院和专业用中点分隔,信息紧凑。
字号稍小,不会喧宾夺主。

编辑按钮

右侧放置编辑按钮:

              IconButton(
                icon: const Icon(Icons.edit, color: Colors.white),
                onPressed: () => Navigator.push(
                  context, 
                  MaterialPageRoute(
                    builder: (_) => const EditProfilePage()
                  )
                ),
              ),
            ],
          ),

白色编辑图标在蓝色背景上清晰可见。
点击后跳转到编辑资料页面。

个性签名

头部底部显示个性签名:

          const SizedBox(height: 16),
          Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Colors.white.withOpacity(0.15),
              borderRadius: BorderRadius.circular(8),
            ),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Icon(
                  Icons.format_quote, 
                  color: Colors.white70, 
                  size: 16
                ),
                const SizedBox(width: 8),

半透明白色背景让签名区域有层次感。
引号图标表示这是一段引用或签名。

签名文字:

                Expanded(
                  child: Text(
                    user.signature.isEmpty 
                        ? '这个人很懒,什么都没写~' 
                        : user.signature,
                    style: const TextStyle(
                      color: Colors.white, 
                      fontSize: 13
                    ),
                    textAlign: TextAlign.center,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }

签名为空时显示默认文字。
居中对齐让签名看起来更美观。

统计卡片

构建统计数据展示卡片:

  Widget _buildStatsCard(AppProvider provider) {
    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Card(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 20),
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              _buildStatItem(
                '加入社团', 
                '${provider.myClubs.length}', 
                Icons.group
              ),
              _buildStatItem(
                '参与活动', 
                '${provider.myActivities.length}', 
                Icons.event
              ),
              _buildStatItem(
                '积分', 
                '${provider.currentUser.points}', 
                Icons.stars
              ),
            ],
          ),
        ),
      ),
    );
  }

Card提供Material风格的卡片效果。
三个统计项均匀分布在卡片中。

单个统计项

构建单个统计项组件:

  Widget _buildStatItem(
    String label, 
    String value, 
    IconData icon
  ) {
    return Column(
      children: [
        Icon(
          icon, 
          color: const Color(0xFF4A90E2), 
          size: 28
        ),
        const SizedBox(height: 8),
        Text(
          value, 
          style: const TextStyle(
            fontSize: 20, 
            fontWeight: FontWeight.bold, 
            color: Color(0xFF4A90E2)
          )
        ),
        const SizedBox(height: 4),
        Text(
          label, 
          style: const TextStyle(
            fontSize: 12, 
            color: Colors.grey
          )
        ),
      ],
    );
  }

图标、数值、标签纵向排列。
数值用粗体蓝色突出显示。

标签用灰色小字作为说明。
这种布局是统计数据的常见展示方式。

功能菜单

构建功能菜单列表:

  Widget _buildMenuSection(BuildContext context) {
    final menuItems = [
      {
        'icon': Icons.group, 
        'title': '我的社团', 
        'page': const MyClubsPage()
      },
      {
        'icon': Icons.event, 
        'title': '我的活动', 
        'page': const MyActivitiesPage()
      },
      {
        'icon': Icons.assignment, 
        'title': '我的任务', 
        'page': const TaskListPage()
      },
      {
        'icon': Icons.message, 
        'title': '消息中心', 
        'page': const MessageCenterPage()
      },

用List存储菜单配置,便于维护。
每个菜单项包含图标、标题和目标页面。

更多菜单项:

      {
        'icon': Icons.account_balance_wallet, 
        'title': '财务管理', 
        'page': const FinanceOverviewPage()
      },
      {
        'icon': Icons.stars, 
        'title': '我的积分', 
        'page': const PointsPage()
      },
      {
        'icon': Icons.feedback, 
        'title': '意见反馈', 
        'page': const FeedbackPage()
      },
      {
        'icon': Icons.info, 
        'title': '关于我们', 
        'page': const AboutPage()
      },
    ];

菜单项涵盖了用户常用的功能入口。
数据驱动的方式让代码更简洁。

渲染菜单列表

遍历配置生成菜单项:

    return Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Card(
        child: Column(
          children: menuItems.map((item) {
            return ListTile(
              leading: Icon(
                item['icon'] as IconData, 
                color: const Color(0xFF4A90E2)
              ),
              title: Text(item['title'] as String),
              trailing: const Icon(
                Icons.chevron_right, 
                color: Colors.grey
              ),
              onTap: () => Navigator.push(
                context, 
                MaterialPageRoute(
                  builder: (_) => item['page'] as Widget
                )
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

map方法遍历配置生成ListTile列表。
ListTile提供标准的列表项布局。

蓝色图标和灰色箭头形成视觉引导。
点击后跳转到对应的功能页面。

渐变背景的设计

头部使用渐变背景有几个好处。
首先让页面更有层次感和设计感。

其次蓝色系和整体风格保持一致。
渐变比纯色更有视觉吸引力。

统计数据的意义

统计卡片让用户快速了解自己的参与情况。
加入的社团数、参与的活动数、积分一目了然。

这些数据也是用户成就感的来源。
看到数字增长会激励用户更多参与。

菜单配置的优势

使用配置数组管理菜单有几个优势。
首先代码更简洁,避免重复的ListTile代码。

其次便于维护,增删菜单只需修改数组。
还可以根据用户权限动态过滤菜单项。

小结

个人中心页面通过渐变背景的用户信息区、统计卡片和功能菜单三个区块组成。用户可以查看个人信息、统计数据,并快速访问各项功能。整体设计简洁实用,符合用户使用习惯。


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

Logo

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

更多推荐