Search code examples
androidflutterlistviewscrollviewbloc

Scrollbar with Listview and bloc in Flutter


I have very simple screen which downloads list of data from internet and shows it via bloc in listview in Flutter. Everything works fine. But I have a problem to add any widget to the top of the listview. If I do it, listview is not shown correctly. I tried to do it as is described here: https://github.com/flutter/flutter/issues/99724 It works if I do not use bloc, but with bloc. Any body did it with bloc ?

  CatalogScreen({super.key});

  final PartRepository partRepository = PartRepository();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: BlocProvider(
        create: (_) => CatalogBloc(partRepository)..add(CatalogFetched()),
        child: const CatalogList(),
      ),
    );
  }
}

class CatalogList extends StatefulWidget {
  const CatalogList({super.key});

  @override
  State<CatalogList> createState() => _CatalogListState();
}

class _CatalogListState extends State<CatalogList> {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<CatalogBloc, FetchCatalogState>(
      builder: (context, state) {
        switch (state.status) {
          case FetchCatalogStatus.failure:
            return Center(child: Text(tr('posts_failed')));
          case FetchCatalogStatus.success:
            if (state.categories.isEmpty) {
              return Center(child: Text(tr('no_parts')));
            }
            return Column(children: [
            const Text('test test'),
            ListView.builder(
              itemBuilder: (BuildContext context, int index) {
                return CatalogListItem(category: state.categories[index]);
              },
              itemCount: state.categories.length,
            )
        ]);
          case FetchCatalogStatus.initial:
            return const Center(child: CircularProgressIndicator());
        }
      },
    );
  }
}

shows this error: RenderBox was not laid out: RenderRepaintBoundary#875f2 relayoutBoundary=up5 NEEDS-PAINT 'package:flutter/src/rendering/box.dart': Failed assertion: line 2009 pos 12: 'hasSize'


Solution

  • The Column above needs a fixed height to render the ListView below with an extra widget on top or bottom. To fix this problem you need to use the Expanded widget at the top of any of the children or all. Like below

    class _CatalogListState extends State<CatalogList> {
      @override
      Widget build(BuildContext context) {
        return BlocBuilder<CatalogBloc, FetchCatalogState>(
          builder: (context, state) {
            switch (state.status) {
              case FetchCatalogStatus.failure:
                return Center(child: Text(tr('posts_failed')));
              case FetchCatalogStatus.success:
                if (state.categories.isEmpty) {
                  return Center(child: Text(tr('no_parts')));
                }
                return Column(children: [
                Expanded(
                  child: const Text('test test'),
                  ),
                Expanded(
                  child: ListView.builder(
                    itemBuilder: (BuildContext context, int index) {
                      return CatalogListItem(category: state.categories[index]);
                    },
                    itemCount: state.categories.length,
                  ),
                )
            ]);
              case FetchCatalogStatus.initial:
                return const Center(child: CircularProgressIndicator());
            }
          },
        );
      }
    }
    

    You can also provide flex as per the height provided