Mesut Tasci
Mesut Tasci

Reputation: 3120

How to prevent auto scroll down on tab2 when user scroll down on tab1 in flutter?

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

Upvotes: 0

Views: 2736

Answers (3)

Elroy
Elroy

Reputation: 1660

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"),
                        );
                    }),
        );
    }
}

Upvotes: 1

bytesizedwizard
bytesizedwizard

Reputation: 6033

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*/
        ]
      )
    )
  }
}

Upvotes: 0

Mazin Ibrahim
Mazin Ibrahim

Reputation: 7869

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
),

Upvotes: 0

Related Questions