带有过滤条件项的列表视图构建器分页(颤振)

Posted

技术标签:

【中文标题】带有过滤条件项的列表视图构建器分页(颤振)【英文标题】:Listview builder pagination with filtered condition items(Flutter) 【发布时间】:2020-08-14 21:36:25 【问题描述】:

我在结构下面有一个列表;

class Data 
  String name;
  int id;
  bool active;

List<Data> _dataList;

我在 Listview.builder 中使用这个列表,如下所示;

ListView.builder(
      shrinkWrap: true,
      scrollDirection: Axis.vertical,
      itemCount: _dataList.length,
      itemBuilder: (context, index) 
          String name= _dataList[index].name;
          String id = _dataList[index].id.toString();
          bool active= _dataList[index].active;
      return 
      active ?
      Card(
         elevation: 5,
         child: Text(name + id));
    
)

我还可以根据此获取过滤后显示的总数和总页码;

var activeList = _dataList.where((c) => c.active == true).toList();
var activeCount = activeList.length;
var totalPages = (activecount/20).ceil();

我想添加一个分页(每页 20 个项目)以使用底部栏图标的“”类型导航,具有上一页和下一页逻辑,如何实现?

我尝试了以下逻辑,但没有成功..

建造者方面:

int page = 1;
int pageCount =0;

ListView.builder(
      shrinkWrap: true,
      scrollDirection: Axis.vertical,
      itemCount: addedCount < 20 ? addedCount : 20,
      itemBuilder: (context, index) 
          String name= activeList[page == 1 ? index : index + pageCount].name;
          String id = activeList[page == 1 ? index : index + pageCount].id.toString();
          bool active= activeList[page == 1 ? index : index + pageCount].active;

图标侧:

Row(
  mainAxisAlignment: MainAxisAlignment.end,
  crossAxisAlignment: CrossAxisAlignment.center ,
    children: <Widget>[
          InkWell(
              onTap: ()
              if (1 < page)page = page - 1; pageCount = pageCount - 20;
              else page = 1;
              setState(() );,
              child: Icon(Icons.arrow_back_ios, size: 35,)),
          Text("$page / $totalPages"),
          InkWell(
              onTap: ()
              if (page < totalPages)page = page + 1; pageCount= pageCount+ 20;
              else page = totalPages;
              setState(() );,
              child: Icon(Icons.arrow_forward_ios, size: 35,)),
             ],
          ),

【问题讨论】:

【参考方案1】:

下面的代码可能会提供一些见解:

class App extends StatefulWidget 
  @override
  AppState createState() => AppState();


class AppState extends State<App> 
  final List<Data> dataList = <Data>[];
  List<Data> currentDataList = <Data>[];
  int page = 1;
  int pageCount = 20;
  int startAt = 0;
  int endAt;
  int totalPages = 0;

  @override
  void initState() 
    for (var i = 1; i <= 100; i++) dataList.add(Data(name: "Test - $i", id: i));

    endAt = startAt + pageCount;
    totalPages = (dataList.length / pageCount).floor();
    if (dataList.length / pageCount > totalPages) 
      totalPages = totalPages + 1;
    

    currentDataList = dataList.getRange(startAt, endAt).toList();
    super.initState();
  

  void loadPreviousPage() 
    if (page > 1) 
      setState(() 
        startAt = startAt - pageCount;
        endAt = page == totalPages
            ? endAt - currentDataList.length
            : endAt - pageCount;
        currentDataList = dataList.getRange(startAt, endAt).toList();
        page = page - 1;
      );
    
  

  void loadNextPage() 
    if (page < totalPages) 
      setState(() 
        startAt = startAt + pageCount;
        endAt = dataList.length > endAt + pageCount ? endAt + pageCount : dataList.length;
        currentDataList = dataList.getRange(startAt, endAt).toList();
        page = page + 1;
      );
    
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      appBar: AppBar(
        title: Text('Pagination'),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: ListView.builder(
              shrinkWrap: true,
              scrollDirection: Axis.vertical,
              itemCount: currentDataList.length,
              itemBuilder: (context, index) 
                return Card(
                  elevation: 5,
                  child: Text(
                    currentDataList[index].name +
                        currentDataList[index].id.toString(),
                  ),
                );
              ,
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              IconButton(
                onPressed: page > 1 ? loadPreviousPage : null,
                icon: Icon(
                  Icons.arrow_back_ios,
                  size: 35,
                ),
              ),
              Text("$page / $totalPages"),
              IconButton(
                onPressed: page < totalPages ? loadNextPage : null,
                icon: Icon(
                  Icons.arrow_forward_ios,
                  size: 35,
                ),
              ),
            ],
          ),
        ],
      ),
    );
  

【讨论】:

这是一种优雅的方法。我的情况只有一个问题,我的列表来自带有查询的firebase数据库,我在initstate中处理查询,所以当我尝试使用你的逻辑时,我的主列表在initstate期间看起来是空的并导致范围错误但我处理它以某种方式。非常感谢。

以上是关于带有过滤条件项的列表视图构建器分页(颤振)的主要内容,如果未能解决你的问题,请参考以下文章

Magnolia 中用于内容列表的分页表视图

带有分隔符的颤振组列表视图

带有列表视图和列的颤振布局

在颤振中添加if条件后,列表视图卡不起作用

使用颤振文档在每个视图图块上创建带有心形图标的随机单词列表视图。 (请在下面找到问题)

如何在颤振/飞镖中缓存列表视图构建器?