请添加图片描述

品牌管理和分类管理类似,都是列表管理页面。不同的是,品牌信息更丰富一些,除了名称还要显示家具数量和总花费。这样用户可以看到在每个品牌上花了多少钱。

做这个功能的时候我在想,其实很多人买家具都有品牌偏好,比如喜欢宜家的简约风,或者喜欢顾家的真皮沙发。有了品牌管理,用户可以清楚地看到自己的品牌消费分布。

页面设计思路

品牌管理页面的设计要点:

  1. 列表展示所有品牌
  2. 每个品牌显示名称首字母作为头像、品牌名称、家具数量、总花费
  3. 点击品牌可以查看该品牌下的所有家具
  4. 右下角有添加按钮

和分类管理的区别是,品牌没有预设图标,用名称首字母作为头像。这种设计在很多 App 里都能看到,比如通讯录。

页面基础结构

品牌管理页面用 StatelessWidget

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

品牌数据暂时写死:

  final _brands = const [
    {'name': '宜家', 'count': 15, 'total': 28600.0},
    {'name': '顾家家居', 'count': 8, 'total': 35200.0},
    {'name': '林氏木业', 'count': 6, 'total': 18500.0},
    {'name': '全友家居', 'count': 5, 'total': 12800.0},
    {'name': '乐歌', 'count': 3, 'total': 6500.0},
    {'name': '源氏木语', 'count': 4, 'total': 9800.0},
  ];

每个品牌有三个属性:名称、家具数量、总花费。这些都是国内比较知名的家具品牌。

build 方法实现

build 方法构建整个页面:

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFFAF8F5),
      appBar: AppBar(
        title: const Text('品牌管理'), 
        backgroundColor: const Color(0xFF8B4513), 
        foregroundColor: Colors.white
      ),
      body: ListView.builder(
        padding: EdgeInsets.all(16.w),
        itemCount: _brands.length,
        itemBuilder: (context, index) => _buildBrandItem(_brands[index]),
      ),

和分类管理页面结构一样,用 ListView.builder 构建列表。

添加按钮

右下角的悬浮添加按钮:

      floatingActionButton: FloatingActionButton(
        onPressed: () => _showAddDialog(),
        backgroundColor: const Color(0xFF8B4513),
        child: const Icon(Icons.add, color: Colors.white),
      ),
    );
  }

点击后弹出添加对话框。

品牌列表项组件

每个品牌是一个卡片,比分类卡片信息更丰富:

  Widget _buildBrandItem(Map<String, dynamic> brand) {
    return Container(
      margin: EdgeInsets.only(bottom: 10.h),
      padding: EdgeInsets.all(16.w),
      decoration: BoxDecoration(
        color: Colors.white, 
        borderRadius: BorderRadius.circular(12.r)
      ),
      child: Row(
        children: [
          Container(
            width: 50.w, 
            height: 50.w,
            decoration: BoxDecoration(
              color: const Color(0xFF8B4513).withOpacity(0.1), 
              borderRadius: BorderRadius.circular(10.r)
            ),
            child: Center(
              child: Text(
                brand['name'].toString().substring(0, 1), 
                style: TextStyle(
                  color: const Color(0xFF8B4513), 
                  fontWeight: FontWeight.bold, 
                  fontSize: 20.sp
                )
              )
            ),
          ),

左边是品牌头像,用品牌名称的第一个字。substring(0, 1) 取第一个字符。

头像容器是 50x50 的正方形,背景是浅棕色,文字是深棕色加粗。这种首字母头像的设计简洁又有辨识度。

品牌信息区域

中间是品牌名称和统计信息:

          SizedBox(width: 14.w),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start, 
              children: [
                Text(
                  brand['name'] as String, 
                  style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16.sp)
                ),
                SizedBox(height: 4.h),
                Text(
                  '${brand['count']}件家具 · ¥${(brand['total'] as double).toStringAsFixed(0)}', 
                  style: TextStyle(color: Colors.grey[600], fontSize: 12.sp)
                ),
              ]
            )
          ),
          IconButton(
            icon: Icon(Icons.chevron_right, color: Colors.grey[400]), 
            onPressed: () {}
          ),
        ],
      ),
    );
  }

品牌名称在上面,用加粗字体。下面是统计信息,用"X件家具 · ¥XXX"的格式,中间用点号分隔。

右边是一个向右的箭头图标,暗示可以点击查看详情。点击后应该跳转到该品牌的家具列表页面。

添加对话框

添加对话框和分类管理一样简单:

  void _showAddDialog() {
    Get.dialog(AlertDialog(
      title: const Text('添加品牌'),
      content: TextField(
        decoration: const InputDecoration(
          hintText: '请输入品牌名称', 
          border: OutlineInputBorder()
        )
      ),
      actions: [
        TextButton(
          onPressed: () => Get.back(), 
          child: const Text('取消')
        ),
        TextButton(
          onPressed: () { 
            Get.back(); 
            Get.snackbar('成功', '品牌添加成功'); 
          }, 
          child: const Text('确定')
        ),
      ],
    ));
  }

只需要输入品牌名称,家具数量和总花费会根据关联的家具自动计算。

首字母头像的设计

用首字母作为头像是一种常见的设计模式,优点是:

  1. 不需要额外的图标资源
  2. 每个品牌都有独特的标识
  3. 实现简单,一行代码搞定

如果品牌名称是英文,取第一个字母;如果是中文,取第一个汉字。substring(0, 1) 对中英文都适用。

如果想让头像更有区分度,可以根据品牌名称生成不同的背景色:

Color _getColorFromName(String name) {
  final colors = [
    Color(0xFF8B4513), Color(0xFF6B8E23), Color(0xFF4682B4),
    Color(0xFF9370DB), Color(0xFFCD853F), Color(0xFF20B2AA),
  ];
  return colors[name.hashCode % colors.length];
}

用名称的 hashCode 对颜色数量取余,这样同一个名称总是得到同一个颜色,不同名称大概率得到不同颜色。

品牌详情页的考虑

点击品牌卡片应该跳转到品牌详情页,显示该品牌下的所有家具。详情页可以复用家具列表的组件,只是数据源不同。

详情页还可以显示一些统计信息:

  • 该品牌的家具数量
  • 总花费
  • 平均单价
  • 购买时间分布

这些信息能帮助用户了解自己在这个品牌上的消费情况。

品牌搜索功能

如果品牌数量很多,可以加一个搜索功能。在 AppBar 加一个搜索按钮,点击后显示搜索框,输入关键词过滤列表。

appBar: AppBar(
  title: const Text('品牌管理'),
  actions: [
    IconButton(
      icon: const Icon(Icons.search),
      onPressed: () {
        // 显示搜索框
      },
    ),
  ],
),

搜索可以用 showSearch 方法,或者自己实现一个搜索框。

品牌排序

品牌列表可以支持多种排序方式:

  • 按名称排序(默认)
  • 按家具数量排序
  • 按总花费排序

在 AppBar 加一个排序按钮,点击后弹出排序选项:

IconButton(
  icon: const Icon(Icons.sort),
  onPressed: () {
    Get.bottomSheet(
      Container(
        color: Colors.white,
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(title: Text('按名称排序'), onTap: () {}),
            ListTile(title: Text('按数量排序'), onTap: () {}),
            ListTile(title: Text('按花费排序'), onTap: () {}),
          ],
        ),
      ),
    );
  },
),

Get.bottomSheet 从底部弹出选项菜单,比对话框更适合这种场景。

品牌合并功能

有时候用户可能会把同一个品牌录入成不同的名称,比如"宜家"和"IKEA"。可以提供一个合并功能,把两个品牌合并成一个。

合并时需要:

  1. 选择保留哪个名称
  2. 把被合并品牌下的家具移到保留的品牌下
  3. 删除被合并的品牌

这个功能比较复杂,可以作为后续优化。

数据统计的价值

品牌管理不只是为了分类,更重要的是数据统计。通过品牌维度的统计,用户可以发现:

  • 自己最喜欢哪个品牌
  • 在哪个品牌上花钱最多
  • 不同品牌的性价比如何

这些信息对于以后的购买决策很有参考价值。比如发现某个品牌的家具质量都不错,以后可能会优先考虑这个品牌。

小结

品牌管理页面和分类管理类似,都是列表管理页面。不同的是品牌用首字母头像,显示的信息更丰富,包括家具数量和总花费。

首字母头像是一种简洁有效的设计,不需要额外资源就能让每个品牌有独特的标识。

下一篇会讲购买记录页面的实现,展示所有的购买记录,支持按时间筛选。


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

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐