Flutter-实现悬浮分组列表

在本篇博客中,我们将介绍如何使用 Flutter 实现一个带有分组列表的应用程序。我们将通过 CustomScrollViewSliver 组件来实现该功能。

需求

我们需要实现一个分组列表,分组包含固定的标题和若干个列表项。具体分组如下:

  • 水果
  • 动物
  • 职业
  • 菜谱

每个分组包含若干个项目,例如水果组包含苹果、香蕉等。

效果

实现思路

  1. 定义数据模型 :创建 ItemBean 类来表示每个分组的数据。
  2. 构建主页面 :使用 CustomScrollViewSliver 组件构建主页面,其中包含多个分组。
  3. 实现固定标题 :通过自定义 SliverPersistentHeaderDelegate 实现固定标题。

实现代码

以下是实现代码:

dart 复制代码
import 'package:flutter/material.dart';

/// 数据源 
/// https://github.com/yixiaolunhui/flutter_xy
class ItemBean {
  final String groupName;
  final List<String> items;

  const ItemBean({required this.groupName, this.items = const []});

  static List<ItemBean> get groupListData => const [
    ItemBean(groupName: '水果', items: [
      '苹果', '香蕉', '橙子', '葡萄', '芒果', '梨', '桃子', '草莓', '西瓜', '柠檬',
      '菠萝', '樱桃', '蓝莓', '猕猴桃', '李子', '柿子', '杏', '杨梅', '石榴', '木瓜'
    ]),
    ItemBean(groupName: '动物', items: [
      '狗', '猫', '狮子', '老虎', '大象', '熊', '鹿', '狼', '狐狸', '猴子',
      '企鹅', '熊猫', '袋鼠', '海豚', '鲨鱼', '斑马', '长颈鹿', '鳄鱼', '孔雀', '乌龟'
    ]),
    ItemBean(groupName: '职业', items: [
      '医生', '护士', '教师', '工程师', '程序员', '律师', '会计', '警察', '消防员', '厨师',
      '司机', '飞行员', '科学家', '记者', '设计师', '作家', '演员', '音乐家', '画家', '摄影师'
    ]),
    ItemBean(groupName: '菜谱', items: [
      '红烧肉', '糖醋排骨', '宫保鸡丁', '麻婆豆腐', '鱼香肉丝', '酸辣汤', '蒜蓉菠菜', '回锅肉', '水煮鱼', '烤鸭',
      '蛋炒饭', '蚝油生菜', '红烧茄子', '西红柿炒鸡蛋', '油焖大虾', '香菇鸡汤', '酸菜鱼', '麻辣香锅', '铁板牛肉', '干煸四季豆'
    ]),
  ];
}

/// 分组列表
class GroupListPage extends StatelessWidget {
  const GroupListPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('分组列表')),
      body: CustomScrollView(
        slivers: ItemBean.groupListData.map(_buildGroup).toList(),
      ),
    );
  }

  Widget _buildGroup(ItemBean itemBean) {
    return SliverMainAxisGroup(
      slivers: [
        SliverPersistentHeader(
          pinned: true,
          delegate: HeaderDelegate(itemBean.groupName),
        ),
        SliverList(
          delegate: SliverChildBuilderDelegate(
            (_, index) => _buildItemByUser(itemBean.items[index]),
            childCount: itemBean.items.length,
          ),
        ),
      ],
    );
  }

  Widget _buildItemByUser(String item) {
    return Container(
      alignment: Alignment.center,
      height: 50,
      child: Row(
        children: [
          const Padding(
            padding: EdgeInsets.only(left: 20, right: 10.0),
            child: FlutterLogo(size: 30),
          ),
          Text(
            item,
            style: const TextStyle(fontSize: 16),
          ),
        ],
      ),
    );
  }
}

class HeaderDelegate extends SliverPersistentHeaderDelegate {
  final String title;

  const HeaderDelegate(this.title);

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      alignment: Alignment.centerLeft,
      color: Colors.grey,
      padding: const EdgeInsets.only(left: 20),
      height: 40,
      child: Text(title, style: const TextStyle(fontSize: 16)),
    );
  }

  @override
  double get maxExtent => 40;

  @override
  double get minExtent => 40;

  @override
  bool shouldRebuild(covariant HeaderDelegate oldDelegate) {
    return title != oldDelegate.title;
  }
}

通过以上代码,我们实现了一个简单的 Flutter 分组列表应用。每个分组都有固定的标题,点击标题可以展开或收起组内的项目。希望这篇博客对你有所帮助!

详情 :github.com/yixiaolunhui/flutter_xy

相关推荐
jcLee9511 小时前
Flutter/Dart:使用日志模块Logger Easier
flutter·log4j·dart·logger
tmacfrank12 小时前
Flutter 异步编程简述
flutter
tmacfrank12 小时前
Flutter 基础知识总结
flutter
叫我菜菜就好13 小时前
【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理
前端·网络·flutter
AiFlutter17 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
m0_748247802 天前
Flutter Intl包使用指南:实现国际化和本地化
前端·javascript·flutter
迷雾漫步者2 天前
Flutter组件————PageView
flutter·跨平台·dart
迷雾漫步者2 天前
Flutter组件————FloatingActionButton
前端·flutter·dart
coder_pig2 天前
📝小记:Ubuntu 部署 Jenkins 打包 Flutter APK
flutter·ubuntu·jenkins
捡芝麻丢西瓜2 天前
flutter自学笔记5- dart 编码规范
flutter·dart