我在自定义有状态小部件中使用PrimaryScrollController
,该小部件基本上是ListView
,其代码可在用户滚动时从服务器加载项目。我需要使用PrimaryScrollController
,以便在iOS上点击应用程序栏的顶部会滚动回到顶部。
我正在多个页面中使用相同的窗口小部件,这些页面由BottomNavigationBar
控制。我还尝试保持状态,以便当用户滚动时,然后切换到底部导航栏中的另一个选项卡,然后返回到第一个选项卡,滚动位置和从服务器加载的所有项目仍将在那里。
要保持页面状态,我正在使用IndexedStack
。但是,由于两个页面都同时使用PrimaryScrollController
,所以我在控制台中得到了一长串的相同错误消息:flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
我了解这是在告诉我不要在多个视图中使用相同的ScrollController
。简单的解决方案是为每个视图创建一个新实例。但是,我必须使用相同的ScrollController
,因为需要PrimaryScrollController
才能点按iOS上的应用程序栏。
如果我只是忽略这些错误,那么实际的代码将按照我想要的方式工作,每个页面都会保留自己的状态。
实际上,它不符合我想要的方式。侦听器位于正确的页面上时不起作用。
我创建了一个示例应用程序来显示问题:
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,
),
],
),
),
);
},
);
}
}
这是引发的错误:
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.
第flutter: Another exception was thrown: ScrollController attached to multiple scroll views.
行不断重复很多次
如何解决此问题?
答案 0 :(得分:0)
旧的,那里有很多答案。几个月前,我遇到了类似的问题:
问题如问题所述,您有多个位置(多个可滚动视图)。
照常声明:
ScrollController scrollController;
//Note,Position,包含关于滚动偏移、物理等的信息,这个“positions”是一个迭代。你可能会猜到,这里是 all 滚动的地方“ position" 被存储(每个附加于此 @scrollController 的可滚动视图一个。
final scrollPositions = scrollController.positions;
//鉴于我抓取了最新的位置长度,在我的用例中总是最后一个(来回执行新列表),您可以根据需要调整它以获取位置信息。< /p>
final scrollPositionImInterested = scrollPositions
.elementAt(scrollController.positions.length - 1);
希望对有相同需求的人有所帮助