0

I created a screen using SliverAppBar, SliverPersistentHeader, TabView and ListView.

If I scroll down in tab1, tab2 scrolling down automatically. So If I swith to tab2, list not starting from first item. How can I prevent this?

I created simple demo app for demonstrate the issue, you can look at this gist.

Initial state of the screen: 1

If I scroll tab1 shown as below: 2

Tab2 scrolling down automatically shown as below when I scroll tab1: 3

Mesut Tasci
  • 2,970
  • 1
  • 30
  • 36

3 Answers3

1

I have modified your gist with PageStorageKey. See below working example:

import 'package:flutter/material.dart';

void main() async {
    runApp(new TestApp());
}


class TestApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return new MaterialApp(
            theme: new ThemeData(primarySwatch: Colors.yellow),
            home: new TestAppHomePage(),
        );
    }
}

class TestAppHomePage extends StatefulWidget {

    @override
    State createState() => new TestAppHomePageState();
    //FPDetailScreen({Key key, @required this.period}) : super(key: key);
}

class TestAppHomePageState extends State<TestAppHomePage>
        with SingleTickerProviderStateMixin {

    @override
    Widget build(BuildContext context) {

        return new Scaffold(
            //bottomNavigationBar: bottomNavBar,
            body: DefaultTabController(
                length: 2,
                child: NestedScrollView(
                    headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
                        return <Widget>[
                            SliverAppBar(
                                expandedHeight: 120.0,
                                floating: false,
                                forceElevated: innerBoxIsScrolled,
                                backgroundColor: Colors.green,
                                pinned: true,
                                flexibleSpace: FlexibleSpaceBar(
                                    collapseMode: CollapseMode.pin,
                                    centerTitle: true,
                                    title: Text(
                                        "Foo Bar Baz",
                                        style: TextStyle(color: Colors.white),
                                        textAlign: TextAlign.left,
                                        overflow: TextOverflow.ellipsis,
                                        softWrap: true,
                                        maxLines: 1,
                                    ),
                                    background: Container(
                                        alignment: Alignment.topCenter,
                                        child: Column(
                                            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                                            children: <Widget>[
                                                Row(
                                                    children: <Widget>[
                                                        Text(
                                                            '10.00 TL',
                                                            style: TextStyle(
                                                                    color: Colors.white,
                                                                    fontSize: 20.0,
                                                                    fontWeight: FontWeight.bold),
                                                        ),

                                                    ],
                                                    mainAxisAlignment: MainAxisAlignment.center,
                                                ),
                                                Container(
                                                    width: 0,
                                                    height: 0,
                                                )
                                            ],
                                        ),
                                    ),
                                    //background: ,
                                ),
                            ),
                            SliverPersistentHeader(
                                pinned: true,
                                delegate: _SliverAppBarDelegate(
                                    TabBar(
                                        tabs: [
                                            Tab(
                                                child: Text(
                                                    "Tab1",
                                                    style: TextStyle(
                                                            color: Colors.black,
                                                            fontWeight: FontWeight.bold),
                                                ),
                                            ),
                                            Tab(
                                                child: Text(
                                                    "Tab2",
                                                    style: TextStyle(
                                                            color: Colors.black,
                                                            fontWeight: FontWeight.bold),
                                                ),
                                            ),
                                        ],
                                    ),
                                ),
                            ),
                        ];
                    },

                    body:TabBarView(
                            //controller: _tabController,
                            children: [
                                CardList('one'),
                                CardList('two'),
                    ]),
                ),
            ),

        );

    }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
    _SliverAppBarDelegate(this._tabBar);

    final TabBar _tabBar;

    @override
    double get minExtent => _tabBar.preferredSize.height;
    @override
    double get maxExtent => _tabBar.preferredSize.height;

    @override
    Widget build(
            BuildContext context, double shrinkOffset, bool overlapsContent) {
        return new Container(
            color: Colors.white,
            child: _tabBar,
        );
    }

    @override
    bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
        return false;
    }
}




class CardList extends StatelessWidget {
    final String listKey;

    CardList(this.listKey);

    @override
    Widget build(BuildContext context) {
        return Container(
            child: ListView.builder(
                    key: PageStorageKey<String>(listKey),
                    scrollDirection: Axis.vertical,
                    shrinkWrap: true,
                    itemCount: 20,
                    //itemExtent: 1.0,
                    itemBuilder: (context, index){
                        return new ListTile(
                            title: new Text("Item $index"),
                        );
                    }),
        );
    }
}
Elroy
  • 1,530
  • 2
  • 15
  • 16
0

The reason behind this issue is that both tabs are using the same TabController which is in your case DefaultTabController which is impilictly defining tab controllers for children widgets, you have to explicitly set a separate TabController for each one of your tabs so its actions is independent of the other, but you will extra code to manage your new controllers:

here's the example:

inside your nestedScrollView

child: nestedScrollView(
controller: // add a `ScrollController` here
),
Mazin Ibrahim
  • 7,433
  • 2
  • 33
  • 40
0

Try wrapping the TabBarView in a separate Scaffold which is inside a StatefulWidget. That way you can ensure that the tab body is rebuilt everytime you change the tab so the scroll position won't be preserved.

Example:

return Scaffold(
  body: DefaultTabController(
    length: 2,
    child: NestedScrollView(
      headerSliverBuilder: /* Your headerSliverBuilder code */
      body: MyCustomTabWidget(),
    )
);

class MyCustomTabWidget extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyCustomTabWidgetState();
  }
}

class MyCustomTabWidgetState extends State<MyCustomTabWidget > {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: new TabBarView(
        children: [
          /*Code for both the Containers containing ListViews*/
        ]
      )
    )
  }
}
bytesizedwizard
  • 5,529
  • 3
  • 17
  • 39
  • How can I open related tab content when user click to tabs if there is seperate `TabBarView`s for each tab? – Mesut Tasci Feb 13 '19 at 08:46
  • My apologies I think I haven't explained it well in the example, it shouldn't be a separate `TabBarView` for each tab. I meant to wrap the entire content on `TabBarView` inside a Scaffold which is in a `StatefulWidget`. I'll update the example code accordingly. – bytesizedwizard Feb 13 '19 at 09:01
  • 1
    Wrapping `TabBarView` with `Scaffold` solved problem, now when I scroll on tab1, tab2 not scrolling automatically but caused another problem: If I scroll down on the screen, `SliverAppBar` not scrolling automatically, `SliverAppBar` should scroll first then tab content should start to scroll. – Mesut Tasci Feb 13 '19 at 11:28
  • I haven't tried running my example with `SilverAppBar` yet. I'll try running the code with `SilverAppBar` and post an update in some time. – bytesizedwizard Feb 13 '19 at 17:40