0

I'm trying to improve my app and want to wrap an existing FutureBuilder with a SliverList. Unfortunately I'm having a strange and incomprehensible scrolling behaviour.

Here's my code so far:

  @override
  Widget build(BuildContext context) {
    return Container(
        child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Expanded(
            child: CustomScrollView(
          slivers: [
            SliverAppBar(
              expandedHeight: 300,
              floating: true,
              flexibleSpace: FlexibleSpaceBar(
                title: Padding(
                  padding: EdgeInsets.fromLTRB(30, 10, 30, 10),
                  child: Text(
                      'some subtext here...',
                      style: TextStyle(
                          fontStyle: FontStyle.italic,
                          color: Colors.white,
                          fontSize: 12.0)),
                ),
                background: Stack(
                  fit: StackFit.expand,
                  children: [
                    Container(
                      child: Image.network(
                        'https://dummyimage.com/600x400/000/fff',
                        fit: BoxFit.cover,
                      ),
                    ),
                    const DecoratedBox(
                      decoration: BoxDecoration(
                        gradient: LinearGradient(
                          begin: Alignment(0.0, 0.5),
                          end: Alignment(0.0, 0.0),
                          colors: <Color>[
                            Color(0xcc000000),
                            Color(0x55000000),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
            SliverPadding(
                padding: EdgeInsets.only(top: 10),
                sliver: SliverList(
                  delegate: SliverChildListDelegate([
                      Container(
                        
                        child: FutureBuilder(
                          future: fetchData(),
                          builder: (BuildContext context, AsyncSnapshot snapshot) {
                            if (snapshot.data == null) {
                              return Text('loading...');
                            } else {
                              return ListView.builder(

                                scrollDirection: Axis.vertical,
                                shrinkWrap: true,

                                itemCount: snapshot.data.length,
                                itemBuilder: (BuildContext content, int index) {
                                  // return Text('Text ' + snapshot.data[index].name);
                                  return snapshot.hasData ? Card(
                                    elevation: 4,
                                    child: ListTile(
                                      leading: CircleAvatar(
                                        backgroundImage:
                                            NetworkImage(snapshot.data[index].image_url),
                                      ),
                                      trailing: Text('Test'),
                                      title: Text(snapshot.data[index].name),
                                      subtitle: Text(snapshot.data[index].latin_name, style: TextStyle(
                                        fontStyle: FontStyle.italic,
                                      )),
                                      onTap: () {
                                        /*Navigator.push(context,
                                          new MaterialPageRoute(builder: (context)=> DetailPage(snapshot.data[index]))
                                        );*/
                                        print('tapped');
                                      },
                                    ),
                                  ) : Text('no Data'); 
                                },
                              );

                              //return Text('loading complete');
                            }
                          }
                        ),
                      ),
                  ],),
                ),
            )
          ],
        )),
      ],
    ));
  }

The SliverAppBar gets displayed correctly, but unfortunately since adding the Slivers my FutureBuilder doesn't display anything at all.

After adding scrollDirection and shrinkWrap to the ListView the data get's displayed but I'm unable to scroll correctly.

When dragging it at the red area the List snaps back up right after releasing The SliverAppBar doesn't shrink either. When scrolling in the green area the Sliver Header works correctly and the Scrolling doesn't snap right at the top when releasing.

Has anyone had this issue before? Or could someone explain on why this could happen?

enter image description here

lechnerio
  • 884
  • 1
  • 16
  • 44
  • I'm not exactly sure what you're trying to achieve by having this Widget structure: `SliverList` -> `FutureBuilder` -> `ListView.builder`. Why not just have a `FutureBuilder`, then once the `Future` has completed, you display the items in either a `ListView` or in a `SliverList`? Also, a note: `FutureBuilder` should be passed an instance of `Future` obtainer earlier, it shouldn't be created during build, as it's going to be restarted on every re-render (which you're getting a lot due to your unorthodox setup and the calling of `fetchData()` during build). – Riwen Feb 01 '21 at 16:13
  • Hi @Riwen, thanks for you answer. unfortunately I don't get it quite yet. Do you mean the other way around, so not like me having the ListView inside the FutureBuilder? – lechnerio Feb 01 '21 at 16:22
  • Yes, that's exactly what I mean. Also, make sure to get the result of `fetchData()` *before* build, so like in `initState` or as an instance member. – Riwen Feb 01 '21 at 17:01

0 Answers0