我使用SliverAppBar
,SliverPersistentHeader
,TabView
和ListView
创建了一个屏幕。
如果我在tab1中向下滚动,则tab2自动向下滚动。因此,如果我切换到tab2,则列表不是从第一项开始。我该如何预防?
我创建了一个简单的演示应用程序来演示该问题,您可以查看此gist。
答案 0 :(得分:0)
此问题背后的原因是,两个标签都使用相同的TabController
(在您的情况下为DefaultTabController
,这是为子窗口小部件非强制性地定义标签控制器,您必须显式设置单独的{{ 1}},以便每个选项卡的操作都独立于其他选项卡,但是您将需要额外的代码来管理新的控制器:
这是示例:
在您的TabController
内
nestedScrollView
答案 1 :(得分:0)
尝试将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*/
]
)
)
}
}
答案 2 :(得分:0)
在这里查看我的解决方法: https://stackoverflow.com/a/54696347/3542938 仍然不是最好的,但是解决它的更好的方法 尝试进行改进,并与我们分享代码
答案 3 :(得分:0)
我已经用PageStorageKey修改了您的gist。参见以下工作示例:
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"),
);
}),
);
}
}