我有一个“ NestedScrollView”,其中包含多个“ TabView”小部件,并且每个选项卡都有一个列表生成器。问题是,当我滚动浏览特定选项卡中的一个列表时,滚动位置会影响其他选项卡中的所有其他列表。
即使我确实将“ ScrollController”添加到每个listview(在选项卡中),选项卡滚动中的listBuilder也与“ NestedScrollView”分开,这是示例代码:
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,) ; } }
3天后,我发现这是解决此问题的最佳方法,但仍需要更多改进,因为sliver标头扩展和收缩太快,您可以改进代码,并与我们分享
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, ); } }