SliverAppBar
我使用、SliverPersistentHeader
和. 创建TabView
了一个屏幕ListView
。
如果我在 tab1 中向下滚动,tab2 会自动向下滚动。因此,如果我切换到 tab2,则列表不是从第一项开始。我怎样才能防止这种情况?
我创建了简单的演示应用程序来演示这个问题,你可以看看这个gist。
SliverAppBar
我使用、SliverPersistentHeader
和. 创建TabView
了一个屏幕ListView
。
如果我在 tab1 中向下滚动,tab2 会自动向下滚动。因此,如果我切换到 tab2,则列表不是从第一项开始。我怎样才能防止这种情况?
我创建了简单的演示应用程序来演示这个问题,你可以看看这个gist。
我已经用 PageStorageKey修改了你的要点。请参见下面的工作示例:
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"),
);
}),
);
}
}
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
),
尝试将 包裹TabBarView
在一个单独的脚手架中,该脚手架位于StatefulWidget
. 这样,您可以确保每次更改选项卡时都重新构建选项卡主体,因此不会保留滚动位置。
例子:
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*/
]
)
)
}
}