gpt4 book ai didi

flutter - 如何同步两个或多个PageView与不同的 Controller

转载 作者:行者123 更新时间:2023-12-05 09:37:15 25 4
gpt4 key购买 nike

我有 2 个具有不同 viewportFraction 的 PageView。有什么方法可以滚动其中一个 PageView,而另一个在同一页面或偏移量上滚动吗?

另外请问,是否可以在代码中控制PageView到偏移量的中间?

class MyPageControllers extends StatefulWidget {
@override
_MyPageControllersState createState() => _MyPageControllersState();
}

class _MyPageControllersState extends State<MyPageControllers> {

PageController _controller1;
PageController _controller2;

Widget _itemBuilder(BuildContext context, int index) => Container(
color: Colors.primaries[index % Colors.primaries.length],
child: Center(
child: Text(
index.toString(),
style: TextStyle(color: Colors.white, fontSize: 60),
),
),
);

@override
void initState() {
super.initState();
_controller1 = PageController(viewportFraction: 0.8);
_controller2 = PageController(viewportFraction: 0.5);
}

@override
Widget build(BuildContext context) {
return Column(
children: [
Expanded(
child: PageView.builder(
controller: _controller1,
itemBuilder: _itemBuilder,
),
),
SizedBox(
height: 40,
),
Expanded(
child: PageView.builder(
controller: _controller2,
itemBuilder: _itemBuilder,
),
),
],
);
}
}

enter image description here

最佳答案

我发现了一个受 @yusufpats 启发的 hacky 解决方案的解决方案。我在下面描述了更多细节:

为每个PageController添加监听器

这部分有点棘手,因为当 Controller 相互监听时,页面实际上会卡住并且无法滚动(为什么?)。我添加 bool 来检查哪个正在滚动并且需要监听。

bool _isPage1Scrolling;
bool _isPage2Scrolling;

void initState() {
_isPage1Scrolling = false;
_isPage2Scrolling = false;

...
_controller1.addListener(() {
if(_isPage1Scrolling){
// Control _controller2
}
}

_controller2.addListener(() {
if(_isPage1Scrolling){
// Control _controller2
}
}

如何控制其他PageController?

这是最难的部分,因为如果我使用animateTojumpTo,“受控 Controller ”看起来很奇怪而且看起来不流畅。这是设计使当用户调用这 2 个函数时,页面将在很短的时间内到达该位置(反弹回稳定的页面位置)后始终转向“BallisticScrollActivity”。我从 Controller 内部的 ScrollPosition 中找到了一些解决方案,但似乎只有最后一个可以很好地解决问题并且结果没有警告:

  1. jumpToWithoutSettling(值):已弃用并可能导致错误(我还不明白)
  2. forcePixels(值): protected 功能(为什么我还能用?)
  3. correctPixels(value):这将在不通知的情况下移动像素。所以我必须自己通知听众。

我使用 offset 作为第一页的位移,并通过 viewportFraction 计算另一页的位移

// Control _controller2

// _controller2.position.jumpToWithoutSettling(...
// _controller2.position.forcePixels(...

_controller2.position.correctPixels(_controller1.offset * _controller2.viewportFraction / _controller1.viewportFraction);
_controller2.position.notifyListeners();

最后听听PageView本身

我使用 NotificationListener 而不是 GestureDetector 因为 onTapDownonTapUp 不适合滚动通知.有时当我快速触摸和滚动时没有 onTapDown 事件。

我研究了通知类型并在里面找到了一些东西:

  1. 当我从头开始拖动它时,它会为 UserScrollNotification 提供方向
  2. 当页面变得稳定时,它给另一个 UserScrollNotification 指示空闲

可能有更好的检测方法。我只是用我能想到的简单方法。

...
child: NotificationListener(
onNotification: (notification){
if(notification is UserScrollNotification){
if(notification.direction != ScrollDirection.idle){
(_controller2.position as ScrollPositionWithSingleContext).goIdle();
_isPage1Scrolling = true;
_isPage2Scrolling = false;
}
else{
_isPage1Scrolling = false;
}
}
return false;
},
child: PageView.builder(
...

也许有人注意到下面一行:

(_controller2.position as ScrollPositionWithSingleContext).goIdle();

此行适用于边缘情况,即如果我拖动第一个 PageView,然后在第一个返回稳定位置之前拖动另一个 PageView。第一个 PageView 的滚动位置仍然处于 BallisticScrollActivity 状态,我需要强制 Idle 它才能控制它。

欢迎提出任何建议!

关于flutter - 如何同步两个或多个PageView与不同的 Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64444606/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com