Home > Back-end >  Two listview builders in a parent listview but not rending only the visibles instead rendering all a
Two listview builders in a parent listview but not rending only the visibles instead rendering all a

Time:08-18

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     body: ListView(
       children: <Widget>[
         _firstListView(),
         _secondListView(),
      ],
    ),
  );
}

Main class that calls tow other listView builders

Widget _firstListView() {
return Container(
  color: Colors.green,
  child: ListView.builder(
    itemCount: 200,
    shrinkWrap: true,
    physics: const ClampingScrollPhysics(),
    itemBuilder: (context, index) => RecCell(
      index: index,
    ),
  ),
);
}

first listView builder

Widget _secondListView() {
return Container(
  color: Colors.red,
  child: ListView.builder(
    itemCount: 200,
    shrinkWrap: true,
    physics: const ClampingScrollPhysics(),
    itemBuilder: (context, index) => ListTile(title: Text("Second $index")),
  ),
);
 }

the second listView builder

RecCell is another statefull widget that prints in init method when the widget is build and it build 200 times on restart and never recreated on scrolling

I want them to resuse each time parent listview scrolls any help will appreciated..

CodePudding user response:

Well, wrapping them in a ListView removes the lazy loading benefit of ListView.builder, because the outer ListView wants to load all children at once. I think the best way is the combine the data of the two ListView.builders into a single one. Although, wrapping them in a colored container would not be possible then, but maybe you get the desired result by wrapping the items in it. So something like:

Widget builds(BuildContext context) {
  return Scaffold(
      body: ListView.builder(
          itemCount: 400,
          shrinkWrap: true,
          itemBuilder: (context, index) => index < 200
              ? Container(
                  color: Colors.green,
                  child: RecCell(
                    index: index,
                  ),
                )
              : Container(
                  color: Colors.red,
                  child: ListTile(title: Text("Second ${index - 200}")))));
}

CodePudding user response:

You could use NestedScrollView if you have nested listview in the body of the parent widget.

CodePudding user response:

try this

  @override
  Widget build(BuildContext context) {
  return Scaffold(
   body: ListView(
     children: <Widget>[
       Container(height: 300, child: _firstListView()),
       Container(height: 300, child: _secondListView()),
     ],
   ),
 );
}

-----------OR------------

 @override
 Widget build(BuildContext context) {
 return Scaffold(
   body: SingleChildScrollView(
     children: <Widget>[
       Container(height: 300, child: _firstListView()),
       Container(height: 300, child: _secondListView()),
     ],
   ),
 );
}

CodePudding user response:

Use CustomScrollView instead ListViews for this case

CustomScrollView(
  slivers: [
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => Container(),
      ),
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => Container(),
      ),
    ),
  ],
);

because the ListView requires all available space and expands its own size as much as possible to understand how many child elements can be displayed

CodePudding user response:

i did this and worked for me

Map<String, dynamic> d = {
   0:..,listView widget,
   1:[...list of widgets]
}

I am making a map containing all my widgets, and in the build method I am returning a listview with those widgets

return ListView(
  children:[
     d[0],
     ...d[1] // this will extract each widget from the list and insert it to list view
  ]
)

In this way my d[0] is horizontal listview builder and d1 are other widget that i am adding into parrent list view directly now they all are rerendering when visibile. Had to do some changing in my previous code

final output output

  • Related