Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sticky tabs in NestedScrollView with ListViews

Tags:

flutter

The layout works as desired, except this:

When I scroll on one page, the second page scrolls too. Not as much but enough to obscure the first item.

I could imagine it'd have something to do with the NestedScrollView but I don't know how to go on.

enter image description here

import 'package:flutter/material.dart';

main(){
  runApp(new MaterialApp(
    home: new MyHomePage(),
  ));
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new DefaultTabController(
      length: 2,
      child: new Scaffold(
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget>[
              new SliverAppBar(
                title: const Text('Tabs and scrolling'),
                forceElevated: innerBoxIsScrolled,
                pinned: true,
                floating: true,
                bottom: new TabBar(
                  tabs: <Tab>[
                    new Tab(text: 'Page 1'),
                    new Tab(text: 'Page 2'),
                  ],
                ),
              ),
            ];
          },
          body: new TabBarView(
            children: <Widget>[
              _list(),
              _list(),
            ],
          ),
        ),
      ),
    );
  }

  Widget _list(){
    return ListView.builder(
      padding: EdgeInsets.zero,
      itemCount: 250,
      itemBuilder: (context, index){
        return Container(
          color: Colors.grey[200].withOpacity((index % 2).toDouble()),
          child: ListTile(
            title: Text(index.toString()),
          ),
        );
      }
    );
  }
}
like image 725
Jakob Avatar asked Nov 24 '25 19:11

Jakob


1 Answers

To be able to keep the two ListViews to scroll without affecting each other they need to have defined controllers.

To have the ListViews maintain their scroll position between tab switching you need to have them in a Widget with AutomaticKeepAliveClientMixin.

Here's an example of what you can do instead of your _list method. Defined a Stateful Widget that returns your lists using both controllers and the AutomaticKeepAliveClientMixin:

class ItemList extends StatefulWidget {
  @override
  _ItemListState createState() => _ItemListState();
}

class _ItemListState extends State<ItemList> with AutomaticKeepAliveClientMixin{
  ScrollController _scrollController = ScrollController();
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return ListView.builder(
      controller: _scrollController,
      padding: EdgeInsets.zero,
      itemCount: 250,
      itemBuilder: (context, index){
        return Container(
          color: Colors.grey[200].withOpacity((index % 2).toDouble()),
          child: ListTile(
            title: Text(index.toString()),
          ),
        );
      }
    );
  }

  @override
  bool get wantKeepAlive => true;
}

You can just call it normally like any other widget inside your TabBarView:

TabBarView(
  children: <Widget>[
    ItemList(),
    ItemList(),
  ],
),
like image 73
João Soares Avatar answered Nov 28 '25 00:11

João Soares



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!