问题
i have "NestedScrollView" that content a "tabView" and every tab view content a "List builder" , when i scroll inside one of list builder (inside tabs) , all other tabs is sync the scroll position if i add "ScrollController" to each listview (in tabs) , then the listBuilder inside the tab scroll separated of "NastedScrollView" here is an example code :
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: MyApp()
,
)
);
class MyApp extends StatefulWidget{
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
TabController tabController;
Widget _tabBarView;
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this,);
_tabBarView = TabBarView(
children: [
DemoTab(),
DemoTab(),
]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
controller: ScrollController(keepScrollOffset: true),
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildListDelegate(
[
Container(height: 300, color: Colors.blue)
]
),
),
];
},
body: DefaultTabController(
length: 2,
child: Column(
children: <Widget>[
Expanded(
child: Container(
child: _tabBarView
),
),
],
),
)
),
);
}
}
class DemoTab extends StatefulWidget{
DemoTabState createState() => DemoTabState();
}
class DemoTabState extends State<DemoTab> with AutomaticKeepAliveClientMixin<DemoTab>{
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
return ListView.builder(
key: UniqueKey(),
itemBuilder: (b, i) {
return Container(
height: 50,
color: Colors.green,
margin: EdgeInsets.only(bottom: 3),
child: Text(i.toString(),),
);
}, itemCount: 30,) ;
}
}
回答1:
after 3 days i found this is the best solution to this problem ,but still need more improvement , cuz the sliver header expand and shrink too fast , you can improve code , and share us
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: MyApp(),
));
class MyApp extends StatefulWidget {
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
TabController tabController;
Widget _tabBarView;
var scrollController = ScrollController();
@override
void initState() {
super.initState();
tabController = TabController(
length: 2,
vsync: this,
);
_tabBarView = TabBarView(children: [
DemoTab(parentController : scrollController),
DemoTab(parentController : scrollController),
]);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: NestedScrollView(
controller: scrollController,
physics: ScrollPhysics(parent: PageScrollPhysics()),
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildListDelegate(
[Container(height: 300, color: Colors.blue)]),
),
];
},
body: DefaultTabController(
length: 2,
child: Column(
children: <Widget>[
Container(
child: TabBar(labelColor: Colors.grey, tabs: [
Tab(
text: 'One',
),
Tab(
text: 'two',
)
]),
),
Expanded(
child: Container(child: _tabBarView),
),
],
),
)),
);
}
}
class DemoTab extends StatefulWidget {
DemoTab({
this.parentController
});
final ScrollController parentController;
DemoTabState createState() => DemoTabState();
}
class DemoTabState extends State<DemoTab>
with AutomaticKeepAliveClientMixin<DemoTab> {
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
ScrollController _scrollController;
ScrollPhysics ph;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener((){
var innerPos = _scrollController.position.pixels;
var maxOuterPos = widget.parentController.position.maxScrollExtent;
var currentOutPos = widget.parentController.position.pixels;
if(innerPos >= 0 && currentOutPos < maxOuterPos) {
//print("parent pos " + currentOutPos.toString() + "max parent pos " + maxOuterPos.toString());
widget.parentController.position.jumpTo(innerPos+currentOutPos);
}else{
var currenParentPos = innerPos + currentOutPos;
widget.parentController.position.jumpTo(currenParentPos);
}
});
widget.parentController.addListener((){
var currentOutPos = widget.parentController.position.pixels;
if(currentOutPos <= 0) {
_scrollController.position.jumpTo(0);
}
});
}
@override
Widget build(BuildContext context) {
return ListView.builder(
key: UniqueKey(),
controller: _scrollController,
itemBuilder: (b, i) {
return Container(
height: 50,
color: Colors.green,
margin: EdgeInsets.only(bottom: 3),
child: Text(
i.toString(),
),
);
},
itemCount: 30,
);
}
}
来源:https://stackoverflow.com/questions/54689594/flutter-tabsview-and-nestedscrollview-scroll-issue