如何在抖动中链接两个综合浏览量?
即如果其中一个进入第x
页,另一个也应进入第x
页。
我以为,两个具有相同控制器的PageView可以解决问题。但这似乎并非如此。
我尝试过列出一个控制器,并且当某个页面浏览量的页面发生更改时,我在所有其他页面浏览量的控制器上调用了jumpToPage
,但其他所有页面浏览量最初不在小部件运行时树中(它们是屏幕外),从而发出错误。
就我而言,PageView(children:[Pageview(...), Pageview(...)])
是结构。
并且一次打开其他网页浏览量后,所有错误均消失了,但是即使移除了当前网页浏览量,它也会被跳转。
[由于没有同时触发其他综合浏览量的事件,因此没有无限循环。
/// Inside a stateful widget
PageView(
controller: widget.controller,
onPageChanged: (pno) {
widget.controllers.where((x) {
return x != widget.controllers[widget.idx];
}).forEach((colpv) {
colpv.controller?.jumpToPage(pno);
});
},
);
这是一个最小的示例,它再现了我在做什么。在ColPageView
小部件中。
完整代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Experiments',
theme: ThemeData.dark(),
home: MyHomePage(title: 'FlutterExps'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<PageControllerC> _controllers;
PageController _rowController;
PageController _mainController;
@override
void initState() {
_controllers = [
PageControllerC(
controller: PageController(keepPage: true),
recorded: 0,
),
PageControllerC(
controller: PageController(keepPage: true),
recorded: 1,
),
];
_controllers.forEach((f) {
f.controller.addListener(() {
print("Listener on ${f.recorded}");
});
});
_mainController = PageController();
_rowController = PageController();
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _rowController,
children: [
ColPageView(
idx: 0,
controllers: _controllers,
controller: _mainController,
children: <Widget>[
ColoredWidget(
color: Colors.cyan,
direction: ">",
),
ColoredWidget(
color: Colors.orange,
direction: ">>",
),
],
),
ColPageView(
idx: 1,
controllers: _controllers,
controller: _mainController,
children: [
ColoredWidget(
color: Colors.green,
direction: "<",
),
ColoredWidget(
color: Colors.yellow,
direction: "<<",
),
],
),
],
),
);
}
}
class PageControllerC {
PageController controller;
int recorded;
PageControllerC({
this.recorded,
this.controller,
});
}
class ColPageView extends StatefulWidget {
final List<Widget> children;
final List<PageControllerC> controllers;
final int idx;
final PageController controller;
const ColPageView({
Key key,
this.children = const <Widget>[],
@required this.controllers,
@required this.idx,
this.controller,
}) : super(key: key);
@override
_ColPageViewState createState() => _ColPageViewState();
}
class _ColPageViewState extends State<ColPageView> {
@override
Widget build(BuildContext context) {
return PageView(
controller: widget.controllers[widget.idx].controller,
// controller: widget.controller,
scrollDirection: Axis.vertical,
children: widget.children,
onPageChanged: (pno) {
widget.controllers.where((x) {
return x != widget.controllers[widget.idx];
}).forEach((colpv) {
// if (colpv != widget.controllers[widget.idx]) {
colpv.controller?.jumpToPage(pno);
// }
// else{
print("memmem ${widget.idx}");
// }
});
print("col-${widget.idx} changed to $pno");
},
);
}
}
class ColoredWidget extends StatefulWidget {
final Color color;
final String direction;
const ColoredWidget({
Key key,
@required this.color,
@required this.direction,
}) : super(key: key);
@override
_ColoredWidgetState createState() => _ColoredWidgetState();
}
class _ColoredWidgetState extends State<ColoredWidget>
with AutomaticKeepAliveClientMixin<ColoredWidget> {
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
color: widget.color,
child: Center(
child: Text(
widget.direction,
style: TextStyle(
fontSize: 100,
color: Colors.black,
),
),
));
}
@override
bool get wantKeepAlive => true;
}
我能够链接两个pageviews
,因为它们都位于pageview
中。
HomePage
小部件中跟踪当前垂直位置。完整代码。
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
SystemChrome.setEnabledSystemUIOverlays([]);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Experiments',
theme: ThemeData.dark(),
home: MyHomePage(title: 'FlutterExps'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
List<PageController> _controllers;
PageController _rowController;
ValueNotifier<int> _horizPage = ValueNotifier(0);
ValueNotifier<int> _vertPage = ValueNotifier(0);
@override
void initState() {
_controllers = [
PageController(keepPage: true),
PageController(keepPage: true),
];
_rowController = PageController();
_horizPage.value = _rowController.initialPage;
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _rowController,
onPageChanged: (pno) {
setState(() {
_horizPage.value = pno;
});
},
children: [
ColPageView(
idx: 0,
currHoriz: _horizPage,
vertstate: _vertPage,
controllers: _controllers,
children: <Widget>[
ColoredWidget(
color: Colors.cyan,
direction: ">",
),
ColoredWidget(
color: Colors.orange,
direction: ">>",
),
],
),
ColPageView(
idx: 1,
currHoriz: _horizPage,
vertstate: _vertPage,
controllers: _controllers,
children: [
ColoredWidget(
color: Colors.green,
direction: "<",
),
ColoredWidget(
color: Colors.yellow,
direction: "<<",
),
],
),
],
),
);
}
}
class ColPageView extends StatefulWidget {
final int idx;
final List<Widget> children;
final List<PageController> controllers;
final ValueNotifier<int> currHoriz;
final ValueNotifier<int> vertstate;
const ColPageView({
Key key,
this.children = const <Widget>[],
@required this.controllers,
@required this.currHoriz,
@required this.vertstate,
@required this.idx,
}) : super(key: key);
@override
_ColPageViewState createState() => _ColPageViewState();
}
class _ColPageViewState extends State<ColPageView> {
@override
void initState() {
widget.controllers[widget.idx] = PageController(
initialPage: widget.vertstate.value ?? 0,
keepPage: true,
);
super.initState();
}
@override
Widget build(BuildContext context) {
return PageView(
controller: widget.controllers[widget.idx],
scrollDirection: Axis.vertical,
children: widget.children,
onPageChanged: (widget.idx == widget.currHoriz.value)
? (pno) {
widget.controllers.forEach((colpv) {
if (colpv != widget.controllers[widget.idx]) {
if (colpv.hasClients && colpv.page != pno) {
colpv.jumpToPage(pno);
}
}
});
// Set latest vertical position
widget.vertstate.value = pno;
// print("col-${widget.idx} changed to $pno");
// set horizontal coord to be null
// As we've finished dealing with it
widget.currHoriz.value = null;
}
: null,
);
}
}
class ColoredWidget extends StatefulWidget {
final Color color;
final String direction;
const ColoredWidget({
Key key,
@required this.color,
@required this.direction,
}) : super(key: key);
@override
_ColoredWidgetState createState() => _ColoredWidgetState();
}
class _ColoredWidgetState extends State<ColoredWidget>
with AutomaticKeepAliveClientMixin<ColoredWidget> {
@override
Widget build(BuildContext context) {
super.build(context);
return Container(
color: widget.color,
child: Center(
child: Text(
widget.direction,
style: TextStyle(
fontSize: 100,
color: Colors.black,
),
),
));
}
@override
bool get wantKeepAlive => true;
}