EdsonBueno / infinite_scroll_pagination

Flutter package to help you lazily load and display pages of items as the user scrolls down your screen.
https://pub.dev/packages/infinite_scroll_pagination
MIT License
633 stars 215 forks source link

Can't use a ScrollView widget as first page progress indicator #160

Closed khoadng closed 2 years ago

khoadng commented 2 years ago

Hi, thanks for this awesome package. However, I have an issue with using a ScrollView widget as a placeholder progress indicator. My use-case is that while waiting for the data to load, the user will see some mockup content before the real content appear.

Reproduce code

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

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: CharacterListView());
  }
}

class CharacterListView extends StatefulWidget {
  const CharacterListView({Key? key}) : super(key: key);

  @override
  _CharacterListViewState createState() => _CharacterListViewState();
}

class _CharacterListViewState extends State<CharacterListView> {
  static const _pageSize = 20;

  final PagingController<int, int> _pagingController = PagingController(firstPageKey: 0);

  @override
  void initState() {
    _pagingController.addPageRequestListener((pageKey) {
      _fetchPage(pageKey);
    });
    super.initState();
  }

  Future<void> _fetchPage(int pageKey) async {
    try {
      final newItems = [1, 2, 3];
      await Future.delayed(const Duration(seconds: 10));
      final isLastPage = newItems.length < _pageSize;
      if (isLastPage) {
        _pagingController.appendLastPage(newItems);
      } else {
        final nextPageKey = pageKey + newItems.length;
        _pagingController.appendPage(newItems, nextPageKey);
      }
    } catch (error) {
      _pagingController.error = error;
    }
  }

  @override
  Widget build(BuildContext context) => CustomScrollView(
        slivers: [
          PagedSliverGrid(
              pagingController: _pagingController,
              builderDelegate: PagedChildBuilderDelegate(
                firstPageProgressIndicatorBuilder: (context) =>
                    ListView(children: ['a', 'b', 'c'].map(Text.new).toList()),
                itemBuilder: (context, item, index) => ListTile(title: Text(item.toString())),
              ),
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                childAspectRatio: 0.65,
                crossAxisCount: 2,
                mainAxisSpacing: 10.0,
                crossAxisSpacing: 10.0,
              ))
        ],
      );

  @override
  void dispose() {
    _pagingController.dispose();
    super.dispose();
  }
}

Error log

The following assertion was thrown during performLayout():
RenderViewport does not support returning intrinsic dimensions.
khoadng commented 2 years ago

Wrapping the ListView in a Container and giving it a width and height value solved the problem.

EArminjon commented 8 months ago

Wrapping firstPageProgressIndicatorBuilder with Sizedbox.shrink or putting shrinkWrapFirstPageIndicators at true can help :)