Reputation: 3120
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.
If I scroll tab1 shown as below:
Tab2 scrolling down automatically shown as below when I scroll tab1:
Upvotes: 0
Views: 2736
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
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
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