Dart 如何在多个视图中同时使用PrimaryScrollController
我正在使用Dart 如何在多个视图中同时使用PrimaryScrollController,dart,flutter,Dart,Flutter,我正在使用PrimaryScrollController在一个定制的有状态小部件中加载项目,该小部件基本上是一个ListView,带有代码,可以在用户滚动时从服务器加载项目。我需要PrimaryScrollController,这样在iOS上点击应用程序栏的顶部就会返回顶部 我在多个页面中使用相同的小部件,这些页面由BottomNavigationBar控制。我还试图保持状态,这样当用户滚动,然后切换到底部导航栏中的另一个选项卡,然后返回到第一个选项卡时,滚动位置和从服务器加载的所有项目仍然存在
PrimaryScrollController
在一个定制的有状态小部件中加载项目,该小部件基本上是一个ListView
,带有代码,可以在用户滚动时从服务器加载项目。我需要PrimaryScrollController
,这样在iOS上点击应用程序栏的顶部就会返回顶部
我在多个页面中使用相同的小部件,这些页面由BottomNavigationBar
控制。我还试图保持状态,这样当用户滚动,然后切换到底部导航栏中的另一个选项卡,然后返回到第一个选项卡时,滚动位置和从服务器加载的所有项目仍然存在
为了保持页面的状态,我使用了索引堆栈
。但是,由于两个页面同时使用primarycrollcontroller
,我在控制台中收到了一长串相同的错误消息:flatter:引发了另一个异常:ScrollController连接到多个滚动视图。
我理解这是在告诉我不应该在多个视图中使用相同的ScrollController
。简单的解决方案是为每个视图创建一个新实例。但是,我必须使用相同的ScrollController
,因为我需要PrimaryScrollController
才能在iOS上点击应用程序栏
如果我只是忽略错误,实际的代码按照我希望的方式工作,每个页面都保留自己的状态。
事实上,它没有按照我想要的方式工作。当听众在sperate页面上时,他们不工作
我创建了一个示例应用程序来显示问题:
import 'package:flutter/material.dart';
import 'dart:math';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
List<Widget> _pages = [
BodyWidget(key: PageStorageKey(1)),
BodyWidget(key: PageStorageKey(2)),
];
class _MyHomePageState extends State<MyHomePage> {
int _currentPage = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: IndexedStack(
index: _currentPage,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentPage,
onTap: (int index) {
setState(() {
_currentPage = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.star_border), title: Text('page 1')),
BottomNavigationBarItem(
icon: Icon(Icons.crop_square), title: Text('page 2'))
]),
);
}
}
class BodyWidget extends StatefulWidget {
BodyWidget({Key key}) : super(key: key);
@override
_BodyWidgetState createState() => _BodyWidgetState();
}
class _BodyWidgetState extends State<BodyWidget> {
ScrollController _scrollController;
List<int> numbers = [];
void dataGenerator() {
// simulate loading items from server
var rng = new Random();
for (var i = 0; i < 100; i++) {
if (this.mounted) {
setState(() {
numbers.add(rng.nextInt(100));
});
}
}
print('loaded more items');
}
@override
void initState() {
super.initState();
// This delay is required to get the build context
Future.delayed(
Duration.zero,
() {
_scrollController = PrimaryScrollController.of(context);
_scrollController.addListener(() {
if (_scrollController.position.pixels >=
(_scrollController.position.maxScrollExtent - 50)) {
dataGenerator();
}
});
dataGenerator();
},
);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: numbers.length,
controller: _scrollController,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Card(
child: Column(
children: <Widget>[
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text('Random number: ' + numbers[index].toString()),
Text('Index: ' + index.toString())
],
),
SizedBox(
height: 15,
),
],
),
),
);
},
);
}
}
导入“包装:颤振/材料.省道”;
导入“dart:math”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
//此小部件是应用程序的根。
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“颤振演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
主页:MyHomePage(标题:“颤振演示主页”),
);
}
}
类MyHomePage扩展StatefulWidget{
MyHomePage({Key,this.title}):超级(Key:Key);
最后的字符串标题;
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
列表页面=[
BodyWidget(键:PageStorageKey(1)),
BodyWidget(键:PageStorageKey(2)),
];
类_MyHomePageState扩展状态{
int _currentPage=0;
@凌驾
小部件构建(构建上下文){
返回脚手架(
appBar:appBar(
标题:文本(widget.title),
),
正文:IndexedStack(
索引:_当前页面,
儿童:_页,
),
底部导航栏:底部导航栏(
currentIndex:_currentPage,
onTap:(int索引){
设置状态(){
_currentPage=索引;
});
},
项目:[
底部导航气压计(
图标:图标(图标。星形边框),标题:文本(“第1页”),
底部导航气压计(
图标:图标(Icons.crop_square),标题:文本(第2页)
]),
);
}
}
类BodyWidget扩展了StatefulWidget{
BodyWidget({Key}):超级(Key:Key);
@凌驾
_BodyWidgetState createState()=>\u BodyWidgetState();
}
类_BodyWidgetState扩展了状态{
ScrollController\u ScrollController;
列表编号=[];
void数据生成器(){
//模拟从服务器加载项目
var rng=新随机数();
对于(变量i=0;i<100;i++){
如果(本安装){
设置状态(){
编号。添加(rng.nextInt(100));
});
}
}
打印(“加载了更多项目”);
}
@凌驾
void initState(){
super.initState();
//获取生成上下文需要此延迟
推迟(
持续时间0.0,
() {
_scrollController=PrimaryScrollController.of(上下文);
_scrollController.addListener((){
如果(_scrollController.position.pixels>=
(_scrollController.position.maxScrollExtent-50)){
数据生成器();
}
});
数据生成器();
},
);
}
@凌驾
小部件构建(构建上下文){
返回ListView.builder(
itemCount:number.length,
控制器:\ u滚动控制器,
itemBuilder:(构建上下文,int索引){
返回容器(
孩子:卡片(
子:列(
儿童:[
大小盒子(
身高:15,
),
划船(
mainAxisAlignment:mainAxisAlignment.space,
儿童:[
Text('随机数:'+数字[index].toString()),
Text('Index:'+Index.toString())
],
),
大小盒子(
身高:15,
),
],
),
),
);
},
);
}
}
这是引发的错误:
flutter: ══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════
flutter: The following assertion was thrown while dispatching notifications for ScrollController:
flutter: ScrollController attached to multiple scroll views.
flutter: 'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 111 pos 12:
flutter: '_positions.length == 1'
flutter:
flutter: Either the assertion indicates an error in the framework itself, or we should provide substantially
flutter: more information in this error message to help you determine and fix the underlying cause.
flutter: In either case, please report this assertion by filing a bug on GitHub:
flutter: https://github.com/flutter/flutter/issues/new?template=BUG.md
flutter:
flutter: When the exception was thrown, this was the stack:
flutter: #2 ScrollController.position
package:flutter/…/widgets/scroll_controller.dart:111
flutter: #3 _BodyWidgetState.initState.<anonymous closure>.<anonymous closure>
package:primaryscrollcontroller_test/main.dart:97
flutter: #4 ChangeNotifier.notifyListeners
package:flutter/…/foundation/change_notifier.dart:206
flutter: #5 ChangeNotifier.notifyListeners
package:flutter/…/foundation/change_notifier.dart:206
flutter: #6 ScrollPosition.notifyListeners
package:flutter/…/widgets/scroll_position.dart:696
flutter: #7 ScrollPosition.setPixels
package:flutter/…/widgets/scroll_position.dart:218
flutter: #8 ScrollPositionWithSingleContext.setPixels
package:flutter/…/widgets/scroll_position_with_single_context.dart:84
flutter: #9 ScrollPositionWithSingleContext.applyUserOffset
package:flutter/…/widgets/scroll_position_with_single_context.dart:127
flutter: #10 ScrollDragController.update
package:flutter/…/widgets/scroll_activity.dart:372
flutter: #11 ScrollableState._handleDragUpdate
package:flutter/…/widgets/scrollable.dart:496
flutter: #12 DragGestureRecognizer.handleEvent.<anonymous closure>
flutter: #13 GestureRecognizer.invokeCallback
package:flutter/…/gestures/recognizer.dart:166
flutter: #14 DragGestureRecognizer.handleEvent
package:flutter/…/gestures/monodrag.dart:182
flutter: #15 PointerRouter._dispatch
package:flutter/…/gestures/pointer_router.dart:73
flutter: #16 PointerRouter.route
package:flutter/…/gestures/pointer_router.dart:101
flutter: #17 _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent
package:flutter/…/gestures/binding.dart:221
flutter: #18 _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent
package:flutter/…/gestures/binding.dart:199
flutter: #19 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent
package:flutter/…/gestures/binding.dart:156
flutter: #20 _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue
package:flutter/…/gestures/binding.dart:102
flutter: #21 _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket
package:flutter/…/gestures/binding.dart:86
flutter: #25 _invoke1 (dart:ui/hooks.dart:233:10)
flutter: #26 _dispatchPointerDataPacket (dart:ui/hooks.dart:154:5)
flutter: (elided 5 frames from class _AssertionError and package dart:async)
flutter:
flutter: The ScrollController sending notification was:
flutter: ScrollController#be798(2 clients)
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
颤振:══╡ 基金会例外╞════════════════════════════════════════════════════════
颤振:为ScrollController发送通知时引发了以下断言:
颤振:连接到多个滚动视图的滚动控制器。
颤振:“包:颤振/src/widgets/scroll\u controller.dart”:失败的断言:第111行位置12:
颤振:'_positions.length==1'
颤振:
颤振:要么断言表明框架本身存在错误,要么我们应该提供
颤振:此错误消息中的更多信息可帮助您确定并修复根本原因。
颤振:无论哪种情况,请在GitHub上提交一个bug来报告这一断言:
颤振:https://github.com/flutter/flutter/issues/new?template=BUG.md
颤振:
颤振:当异常w
ScrollController scrollController;
final scrollPositions = scrollController.positions;
final scrollPositionImInterested = scrollPositions
.elementAt(scrollController.positions.length - 1);