dart - 如何在多个视图中同时使用 PrimaryScrollController
问题描述
我PrimaryScrollController
在自定义有状态小部件中使用 to,它基本上是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.
只是不断重复很多次
我该如何解决这个问题?
解决方案
旧的,那里有很多答案。几个月前我有类似的问题:
问题指出,您有多个职位(几个可滚动视图)。
像往常一样声明:
ScrollController scrollController;
//注意,位置,包含有关滚动偏移、物理等的信息,这个“位置”是一个可迭代的。你可能会猜到,这里存储了所有滚动“位置”(每个为这个@附加的可滚动视图一个)滚动控制器”。
final scrollPositions = scrollController.positions;
//给定位置长度我抓取了最新的,在我的用例中总是最后一个(来回做新列表),您可以根据需要对其进行调整以获取位置信息。
final scrollPositionImInterested = scrollPositions
.elementAt(scrollController.positions.length - 1);
希望这可以帮助有相同需求的人
推荐阅读
- alexa - 如何从传感器发送 Alexa 智能家居主动变更报告?
- algorithm - 求二叉树高度的递归关系和时间复杂度
- r - 如何根据结束日期和天数计算开始日期
- c# - 让 .net SqlConnection 无限期打开与 using 块
- xcode - 如何将 tensorflow-lite 模型转换为 coreml .mlmodel
- api - 除了 API 调用或套接字之外,还有其他从服务器获取实时数据的选项吗?
- android - 如何从 recyclerview 项目中打开活动?
- android - 适用于 Android 的类似 iOS 的导航抽屉?
- sql - 按两个条件分组
- java - 尝试在 Eclipse Maven 项目中配置 Cucumber 时出现 Runner 类中的错误