按日期分组的列表视图 Dart

Sim*_*mon 4 listview dart flutter

我一直在尝试按日期排序一些消息,但我没有让它工作。我尝试过不同的包,如grouped_liststicky_headers

使用sticky_headers,我设法在每个帖子上方都有一个标题,但这不是我想要的。我想按天对消息进行排序。像下面的图片:
应用实例

下面我有一个数据集,其中包含从我的 API 获得的数据。我的目的是从 API 获取 40 条消息。这 40 条消息按时间排序,只有消息必须在应用程序中按天分组,如上图所示。

编辑:在flutter上玩过sticky_header包之后。我现在已经设法获得标题。只是没有设法在正确的标题下获取消息。

数据集:

[
  {
    "time": "2020-06-16T10:31:12.000Z",
    "message": "P2 BGM-01 HV buiten materieel (Gas lekkage) Franckstraat Arnhem 073631"
  },
  {
    "time": "2020-06-16T10:29:35.000Z",
    "message": "A1 Brahmslaan 3862TD Nijkerk 73278"
  },
  {
    "time": "2020-06-16T10:29:35.000Z",
    "message": "A2 NS Station Rheden Dr. Langemijerweg 6991EV Rheden 73286"
  },
  {
    "time": "2020-06-15T09:41:18.000Z",
    "message": "A2 VWS Utrechtseweg 6871DR Renkum 74636"
  },
  {
    "time": "2020-06-14T09:40:58.000Z",
    "message": "B2 5623EJ : Michelangelolaan Eindhoven Obj: ziekenhuizen 8610 Ca CATH route 522 PAAZ Rit: 66570"
  }
]
Run Code Online (Sandbox Code Playgroud)

mah*_*mnj 23

您应该能够通过一些自定义的日期逻辑来实现这一点。如果不在这些列表项之间添加文本标题,请检查两个连续日期是否相同。

下面是上述方法的实现。

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

void main() {
  final dateString = '2020-06-16T10:31:12.000Z';
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
 
  List<Map> list = [
    {
      "time": "2020-06-16T10:31:12.000Z",
      "message":
          "P2 BGM-01 HV buiten materieel (Gas lekkage) Franckstraat Arnhem 073631"
    },
    {
      "time": "2020-06-16T10:29:35.000Z",
      "message": "A1 Brahmslaan 3862TD Nijkerk 73278"
    },
    {
      "time": "2020-06-16T10:29:35.000Z",
      "message": "A2 NS Station Rheden Dr. Langemijerweg 6991EV Rheden 73286"
    },
    {
      "time": "2020-06-15T09:41:18.000Z",
      "message": "A2 VWS Utrechtseweg 6871DR Renkum 74636"
    },
    {
      "time": "2020-06-14T09:40:58.000Z",
      "message":
          "B2 5623EJ : Michelangelolaan Eindhoven Obj: ziekenhuizen 8610 Ca CATH route 522 PAAZ Rit: 66570"
    }
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: ListView.builder(
            itemCount: list.length,
            itemBuilder: (_, index) {
              bool isSameDate = true;
              final String dateString = list[index]['time'];
              final DateTime date = DateTime.parse(dateString);
              final item = list[index];
              if (index == 0) {
                isSameDate = false;
              } else {
                final String prevDateString = list[index - 1]['time'];
                final DateTime prevDate = DateTime.parse(prevDateString);
                isSameDate = date.isSameDate(prevDate);
              }
              if (index == 0 || !(isSameDate)) {
                return Column(children: [
                  Text(date.formatDate()),
                  ListTile(title: Text('item $index'))
                ]);
              } else {
                return ListTile(title: Text('item $index'));
              }
            }),
      ),
    );
  }
}

const String dateFormatter = 'MMMM dd, y';

extension DateHelper on DateTime {
  
   String formatDate() {
     final formatter = DateFormat(dateFormatter);
      return formatter.format(this);
  }
  bool isSameDate(DateTime other) {
    return this.year == other.year &&
        this.month == other.month &&
        this.day == other.day;
  }

  int getDifferenceInDaysWithNow() {
    final now = DateTime.now();
    return now.difference(this).inDays;
  }
}

Run Code Online (Sandbox Code Playgroud)

输出

在此输入图像描述

  • 我发现这个答案因其简洁的性质而更好,并且不依赖于另一个包。 (4认同)

Mur*_*dla 11

首先,分解您的代码以从数据集中按日期映射获取分组。然后使用此地图构建 UI。

使用集合包来使用 groupBy 函数。

import "package:collection/collection.dart";

void main() {
  final dataSet = [
    {
      "time": "2020-06-16T10:31:12.000Z",
      "message": "Message1",
    },
    {
      "time": "2020-06-16T10:29:35.000Z",
      "message": "Message2",
    },
    {
      "time": "2020-06-15T09:41:18.000Z",
      "message": "Message3",
    },
  ];

  var groupByDate = groupBy(dataSet, (obj) => obj['time'].substring(0, 10));
  groupByDate.forEach((date, list) {
    // Header
    print('${date}:');

    // Group
    list.forEach((listItem) {
      // List item
      print('${listItem["time"]}, ${listItem["message"]}');
    });
    // day section divider
    print('\n');
  });
}
Run Code Online (Sandbox Code Playgroud)

输出:

2020-06-16:
2020-06-16T10:31:12.000Z, Message1
2020-06-16T10:29:35.000Z, Message2


2020-06-15:
2020-06-15T09:41:18.000Z, Message3
Run Code Online (Sandbox Code Playgroud)

我希望这个片段能帮助你开始构建你的 UI。您可以将ListView小部件用于每个组中的列表项。

通过DateTimeDateFormat类来处理日期、时间值。


Cas*_*rin 9

有一些名为Sticky_grouped_listgrouped_list的 dart.pub 软件包(在您的问题中提到)。他们通过公共属性围绕组元素做了很好的工作。我已经尝试过 Sticky_grouped_list并且我没有在您的特定场景中使用它,一旦列表可以按动态类型对元素进行分组,它似乎适用于它。

除了外观之外,您的代码与该示例之间的主要功能差异是它们使用了 DateTime 元素而不是 String 作为对列表进行分组的更好方式。粘性组列表视图很有趣,因为当前日期在向下滚动时会粘在屏幕顶部。

在此输入图像描述

instead of using a ListView create a GroupedListView Widget:

  GroupedListView<dynamic, String>(
    elements: _elements,
    groupBy: (element) => element['group'],
    groupSeparatorBuilder: (String groupByValue) => Text(groupByValue),
    itemBuilder: (context, dynamic element) => Text(element['name']),
    order: GroupedListOrder.ASC,
  ),
Run Code Online (Sandbox Code Playgroud)

使用 StickyGroupedListView,您还可以按自定义对象进行分组:

StickyGroupedListView<CustomObject, DateTime>(
  elements: pedidos,
  order: StickyGroupedListOrder.ASC,
  groupBy: (CustomObject element) => DateTime(
      element.dateGroup.year,
      element.dateGroup.month,
      element.dateGroup.day),
  groupSeparatorBuilder: (CustomObject element) =>
      renderDataCabecalho(element),
  itemBuilder: (context, element) {
    return _buildPedidoItemView(element, context);
  },
),
Run Code Online (Sandbox Code Playgroud)

如果它不适用于您的需求,您可能可以了解他们对元素进行分组的方法。