首页 > 解决方案 > 在customScrollView中滚动到底部时如何检测并运行加载功能

问题描述

当用户滚动到 customScrollView 内列表的底部时,我正在尝试运行更多负载。

我正在使用粘性标题进行一些排序,因此必须使用带有flutter_sticky_header包的条子。

这是页面代码

class SoldEntryScreen extends StatelessWidget {
  const SoldEntryScreen({
    Key key,
    this.isDataLoading,
    this.isNextPageAvailable,
    this.transactions,
    this.loadNextPage,
    this.noError,
  });

  final bool isDataLoading;
  final bool isNextPageAvailable;
  final transactions;
  final Function loadNextPage;
  final bool noError;

  @override
  Widget build(BuildContext context) {
    var history = {};

    transactions.forEach((element) {
      final formatedDate = Utils.dateFormater(element.createdAt);
      if ((history[formatedDate['dateClass']] == null))
        return (history[formatedDate['dateClass']] = [element]);
      return history[formatedDate['dateClass']].add(element);
    });
    print(history);
    return AppScaffold(
      title: 'List Example',
      slivers: [
        SliverToBoxAdapter(
          child: SoldEntryPage(),
        ),
        _StickyHeaderDateSort(history: history),
      ],
    );
  }
}

class _StickyHeaderList extends StatelessWidget {
  const _StickyHeaderList({
    Key key,
    this.keyTitle,
    this.keyData,
  }) : super(key: key);

  final keyTitle;
  final keyData;

  @override
  Widget build(BuildContext context) {
    print(keyData);
    return SliverStickyHeader(
      header: Header(title: keyTitle),
      sliver: SliverToBoxAdapter(
        child: Container(
          child: ListView.separated(
            shrinkWrap: true,
            physics: ClampingScrollPhysics(),
          itemCount: keyData.length,
          itemBuilder: (context, index) {
            return MoneyTransactionModelListItem(
                            itemIndex: index, transaction: keyData[index]);
          },
          separatorBuilder: (BuildContext context, int index) =>
              Divider(color: Theme.of(context).dividerColor),
        ),
        )
      ),
    );
  }
}

class _StickyHeaderDateSort extends StatelessWidget {
  const _StickyHeaderDateSort({
    Key key,
    this.history,
  }) : super(key: key);

  final history;

  @override
  Widget build(BuildContext context) {
    return SliverStickyHeader(
      header: HeaderDatePicker(),
      sliver: SliverToBoxAdapter(
        child: ShrinkWrappingViewport(
          offset: ViewportOffset.zero(),
          slivers: [
            for (var key in history.keys)
              _StickyHeaderList(keyTitle: key, keyData: history[key])
          ],
        ),
      ),
    );
  }
}

看起来像这样

在此处输入图像描述

这是AppScaffold小部件

class AppScaffold extends StatelessWidget {
  const AppScaffold({
    Key key,
    @required this.title,
    @required this.slivers,
    this.reverse = false,
  }) : super(key: key);

  final String title;
  final List<Widget> slivers;
  final bool reverse;

  @override
  Widget build(BuildContext context) {
    return DefaultStickyHeaderController(
      child: CustomScrollView(
        slivers: slivers,
        reverse: reverse,
      ),
    );
  }
}

标签: flutterdartflutter-layout

解决方案


这是一个 ListView 的基本示例,它在底部被击中时加载更多元素。NotificationListener<ScrollNotification>基本上每个滚动都会通知的想法,并会为您scrollNotification提供可以用来查看您是否位于 ListView 底部的想法。

这是代码:

import 'package:flutter/material.dart';

main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Container> containerList = [
    Container(
      color: Colors.red,
      height: 200,
    ),
    Container(
      color: Colors.blue,
      height: 200,
    ),
    Container(
      color: Colors.green,
      height: 200,
    ),
    Container(
      color: Colors.yellow,
      height: 200,
    ),
  ];
  bool isUpdating = false;

  Future<void> addNewWidgets() async {
    isUpdating = true;

    Future.delayed(Duration(seconds: 1), () {
      setState(() {
        containerList.addAll([
          Container(
            color: Colors.red,
            height: 200,
          ),
          Container(
            color: Colors.blue,
            height: 200,
          ),
          Container(
            color: Colors.green,
            height: 200,
          ),
          Container(
            color: Colors.yellow,
            height: 200,
          ),
        ]);
      });

      print('state changed ${containerList.length}');
      isUpdating = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: NotificationListener<ScrollNotification>(
          onNotification: (scrollNotification) {
            if (scrollNotification.metrics.pixels >=
                    scrollNotification.metrics.maxScrollExtent &&
                !isUpdating) {
              addNewWidgets();
            }
            return true;
          },
          child: ListView.builder(
            itemCount: containerList.length,
            itemBuilder: (BuildContext context, int index) {
              return containerList[index];
            },
          ),
        ),
      ),
    );
  }
}

我没有使用sticky_header,但我相信您可以使用此方法使其工作。


推荐阅读