请添加图片描述

收藏夹页面展示用户收藏的家具。用户可以把重要的或喜欢的家具加入收藏,方便以后快速查看。这个页面的设计比较简洁,主要是一个卡片列表。

做收藏功能的时候我在想,有些家具可能是用户特别喜欢的,或者是需要重点关注的(比如快过保的),加入收藏后就不用在长长的列表里找了。

页面设计思路

收藏夹页面的设计要点:

  1. 列表展示收藏的家具
  2. 每个卡片显示家具图片占位、名称、品牌、房间、价格
  3. 卡片右下角有取消收藏按钮
  4. 没有收藏时显示空状态引导

卡片设计比普通列表项更丰富,左边有图片占位区域,让页面更有视觉层次。

页面基础结构

收藏夹页面用 StatelessWidget

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

收藏数据暂时写死:

  final _favorites = const [
    {'name': '北欧实木沙发', 'room': '客厅', 'brand': '宜家', 'price': 12800.0},
    {'name': '智能升降书桌', 'room': '书房', 'brand': '乐歌', 'price': 3200.0},
    {'name': '真皮双人床', 'room': '卧室', 'brand': '顾家', 'price': 8500.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: _favorites.isEmpty 
        ? _buildEmpty() 
        : ListView.builder(
            padding: EdgeInsets.all(16.w),
            itemCount: _favorites.length,
            itemBuilder: (context, index) => _buildFavoriteCard(_favorites[index]),
          ),
    );
  }

根据收藏列表是否为空显示不同内容。

空状态组件

没有收藏时显示空状态:

  Widget _buildEmpty() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.favorite_border, size: 80.sp, color: Colors.grey[300]),
          SizedBox(height: 16.h),
          Text('暂无收藏', style: TextStyle(color: Colors.grey[500], fontSize: 16.sp)),
          SizedBox(height: 8.h),
          Text('点击家具详情页的❤️添加收藏', 
            style: TextStyle(color: Colors.grey[400], fontSize: 13.sp)),
        ],
      ),
    );
  }

空状态显示一个空心爱心图标和引导文字,告诉用户如何添加收藏。

收藏卡片组件

每个收藏是一个横向卡片:

  Widget _buildFavoriteCard(Map<String, dynamic> item) {
    return Container(
      margin: EdgeInsets.only(bottom: 12.h),
      decoration: BoxDecoration(
        color: Colors.white, 
        borderRadius: BorderRadius.circular(16.r)
      ),
      child: Row(
        children: [
          Container(
            width: 100.w, 
            height: 100.w,
            decoration: BoxDecoration(
              color: const Color(0xFF8B4513).withOpacity(0.1),
              borderRadius: BorderRadius.horizontal(left: Radius.circular(16.r)),
            ),
            child: Center(
              child: Icon(Icons.chair, size: 40.sp, 
                color: const Color(0xFF8B4513).withOpacity(0.5))
            ),
          ),

左边是图片占位区域,用浅棕色背景和半透明图标。实际项目中这里应该显示家具的真实图片。

BorderRadius.horizontal(left: ...) 只给左边设置圆角,和卡片的左边圆角对齐。

家具信息区域

右边是家具信息:

          Expanded(
            child: Padding(
              padding: EdgeInsets.all(12.w),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(item['name'] as String, style: TextStyle(
                    fontWeight: FontWeight.bold, 
                    fontSize: 15.sp
                  )),
                  SizedBox(height: 4.h),
                  Text('${item['brand']} · ${item['room']}', style: TextStyle(
                    color: Colors.grey[600], 
                    fontSize: 12.sp
                  )),
                  SizedBox(height: 8.h),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text('¥${(item['price'] as double).toStringAsFixed(0)}', 
                        style: TextStyle(
                          color: const Color(0xFF8B4513), 
                          fontWeight: FontWeight.bold, 
                          fontSize: 16.sp
                        )),
                      IconButton(
                        icon: const Icon(Icons.favorite, color: Colors.red),
                        onPressed: () => Get.snackbar('已取消', '已从收藏中移除'),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

显示名称、品牌和房间、价格。右下角是红色实心爱心按钮,点击取消收藏。

收藏状态管理

实际项目中,收藏状态应该用状态管理:

class FavoritesController extends GetxController {
  final favorites = <Map<String, dynamic>>[].obs;
  
  void addFavorite(Map<String, dynamic> item) {
    if (!favorites.any((f) => f['id'] == item['id'])) {
      favorites.add(item);
    }
  }
  
  void removeFavorite(String id) {
    favorites.removeWhere((f) => f['id'] == id);
  }
  
  bool isFavorite(String id) {
    return favorites.any((f) => f['id'] == id);
  }
}

用 GetX 的响应式变量管理收藏列表,添加、移除、判断是否收藏都通过 Controller 操作。

家具详情页的收藏按钮

在家具详情页添加收藏按钮:

IconButton(
  icon: Icon(
    controller.isFavorite(furniture['id']) 
      ? Icons.favorite 
      : Icons.favorite_border,
    color: controller.isFavorite(furniture['id']) 
      ? Colors.red 
      : Colors.grey,
  ),
  onPressed: () {
    if (controller.isFavorite(furniture['id'])) {
      controller.removeFavorite(furniture['id']);
      Get.snackbar('已取消', '已从收藏中移除');
    } else {
      controller.addFavorite(furniture);
      Get.snackbar('已收藏', '已添加到收藏夹');
    }
  },
)

根据收藏状态显示实心或空心爱心,点击切换状态。

收藏排序

收藏列表可以支持排序:

enum SortType { byTime, byName, byPrice }

List<Map<String, dynamic>> _sortFavorites(SortType type) {
  final list = List<Map<String, dynamic>>.from(_favorites);
  switch (type) {
    case SortType.byTime:
      // 按收藏时间排序
      break;
    case SortType.byName:
      list.sort((a, b) => (a['name'] as String).compareTo(b['name'] as String));
      break;
    case SortType.byPrice:
      list.sort((a, b) => (a['price'] as double).compareTo(b['price'] as double));
      break;
  }
  return list;
}

可以在 AppBar 加一个排序按钮,让用户选择排序方式。

批量操作

可以支持批量取消收藏:

bool _isSelecting = false;
Set<String> _selectedIds = {};

Widget _buildSelectableCard(Map<String, dynamic> item) {
  final isSelected = _selectedIds.contains(item['id']);
  return GestureDetector(
    onTap: () {
      if (_isSelecting) {
        setState(() {
          if (isSelected) {
            _selectedIds.remove(item['id']);
          } else {
            _selectedIds.add(item['id']);
          }
        });
      }
    },
    child: Stack(
      children: [
        _buildFavoriteCard(item),
        if (_isSelecting)
          Positioned(
            top: 8, right: 8,
            child: Icon(
              isSelected ? Icons.check_circle : Icons.radio_button_unchecked,
              color: isSelected ? const Color(0xFF8B4513) : Colors.grey,
            ),
          ),
      ],
    ),
  );
}

长按进入选择模式,点击选中/取消选中,底部显示批量操作按钮。

小结

收藏夹页面展示用户收藏的家具,用横向卡片布局,左边是图片占位,右边是家具信息。空状态显示引导文字,告诉用户如何添加收藏。

收藏功能需要状态管理,在家具详情页添加收藏按钮,收藏夹页面显示收藏列表。

下一篇会讲商家管理页面的实现,展示购买家具的商家信息。


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

Logo

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

更多推荐