简体   繁体   中英

Can I integrate my dynamic JSON derived Listview with a SliverList in Flutter?

What my app currently does

I have a nice App scaffold with an Appbar and a listview underneath it.

I use a widget to pull JSON data via ThreadData and build a listview with it as follows.

  • I've cut a lot of the styling out to keep this short.
  • PostCard references a widget that returns a Card() with all my stylized data, its just a bunch of Containers Rows and Text
Scaffold(
    appBar: AppBar(
      elevation:0,
      centerTitle: false,
      title: Text("title")
      ),
    body:
    Container(
          child: 
                    Consumer<ThreadData>(
                          builder: (context, value, child) {
                            return value.map.length == 0 && !value.error
                                ? CircularProgressIndicator() // if there is no data but there is no error then show the progress bar
                                : value.error ? Text('Oops, something went wrong.\n\n ${value.errorMessage}', textAlign:TextAlign.center) //otherwise there was an error, then show the error
                                : ListView.builder(
                              itemCount: value.map["appData"]["posts"].length,
                              itemBuilder: (context, index) {
                        
                                  return PostCard(map: value.map["appData"]["posts"][index]);
                                  
                              },
                            );
                          },
                        )
        ),
      );

Converting it to a Sliver with CustomScrollView so I can get animated headers

So in attempting to convert this to a sliver setup I've gotten the following which works with some randomly generated text -- not the JSON data I'm ultimately going to use

Scaffold(
      // No appBar property provided, only the body.
      body: CustomScrollView(
        slivers: <Widget>[
        // Add the app bar to the CustomScrollView.
        SliverAppBar(
              title: Text('y0y0'),
              floating: true,
              flexibleSpace: Placeholder(),
              expandedHeight: 200,
              ),
          SliverList(
            // Use a delegate to build items as they're scrolled on screen.
            delegate: SliverChildBuilderDelegate(
                  (context, index) => ListTile(title: Text('Item #$index')),
                  childCount: 1000,
            ),
          )
    ],
    )
    );

This is where I'm stuck

I'm trying to get my original Listview into the SliverList so that I can have the fancy slivery Appbar and my dynamic listview data.

No matter how I try to jam my original code's Consumer<ThreadData>() block into the new Sliverlist() nothing seems to work. The closest I've gotten is a list of 1000 loader circles

Total fail:

Scaffold(
      // No appBar property provided, only the body.
      body: CustomScrollView(
        slivers: <Widget>[
        // Add the app bar to the CustomScrollView.
        SliverAppBar(
              title: Text('y0y0'),
              floating: true,
              flexibleSpace: Placeholder(),
              expandedHeight: 200,
              ),
          SliverList(
            // Use a delegate to build items as they're scrolled on screen.
            delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
    // To convert this infinite list to a list with three items,
    // uncomment the following line:
    // if (index > 3) return null;
    return                     Consumer<ThreadData>(
      builder: (context, value, child) {
        return value.map.length == 0 && !value.error
            ? CircularProgressIndicator() // if there is no data but there is no error then show the progress bar
            : value.error ? Text('Oops, something went wrong.\n\n ${value.errorMessage}', textAlign:TextAlign.center) //otherwise there was an error, then show the error
            : ListView.builder(
          itemCount: value.map["appData"]["posts"].length,
          itemBuilder: (context, index) {

            return PostCard(map: value.map["appData"]["posts"][index]);

          },
        );
      },
    );
    
    },
          )
          )
    ],
    )
    );

    }
}

One way this should work is like so.

CustomScrollView(
  slivers: [
    SliverAppBar(
      //app bar properties
    ),
    Consumer<ThreadData>(
      builder: (_, value, __) {
        if (value.map.length == 0 && !value.error) {
          return SliverToBoxAdapter(child: CircularProgressIndicator());
        } else if (value.error) {
          return SliverToBoxAdapter(
            child: Text(
              'Oops, something went wrong.\n\n ${value.errorMessage}',
              textAlign: TextAlign.center,
            ),
          );
        } else {
          return SliverList(
            delegate: SliverChildBuilderDelegate(
              (_, index) => PostCard(
                map: value.map["appData"]["posts"][index],
              ),
              childCount: value.map["appData"]["posts"].length,
            ),
          );
        }
      },
    ),
  ],
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM