Recursion 多个可滚动小部件的滚动同步

Recursion 多个可滚动小部件的滚动同步,recursion,dart,flutter,Recursion,Dart,Flutter,多个可滚动小部件的滚动同步: 如果滚动第一个列表,我想滚动第二个列表,如果滚动第二个列表,我想滚动第一个列表。这将是递归的。任何人都可以为此提供帮助,提前感谢 import 'package:flutter/cupertino.dart'; class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePa

多个可滚动小部件的滚动同步:

如果滚动第一个列表,我想滚动第二个列表,如果滚动第二个列表,我想滚动第一个列表。这将是递归的。任何人都可以为此提供帮助,提前感谢

import 'package:flutter/cupertino.dart';
class MyHomePage extends StatefulWidget {
 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ScrollController firstScroll = ScrollController();
  ScrollController secondScrollController = ScrollController();

  @override
  void initState() {
     super.initState();
     firstScroll.addListener(() {
    //THIS IS called when scroll is triggered,
        secondScrollController
           .jumpTo(firstScroll.offset); // THIS will sync the scroll;
     });

 secondScrollController.addListener(() {
    //THIS IS called when scroll is triggered,
        firstScroll
           .jumpTo(secondScrollController.offset); // THIS will sync the scroll;
     });
   }

   @override
   Widget build(BuildContext context) {
     return Container(
        child: Column(
          children: <Widget>[
            SingleChildScrollView(
             // this is the first scroll
                scrollDirection: Axis.horizontal,
                controller: firstScroll, // THIS IS THE FIRST SCROLL CONTROLLER
                child: Container(
                   //TODO: add your content here here
                ),
            ),
            SingleChildScrollView(
               scrollDirection: Axis.horizontal,
               controller: secondScrollController,
               // HERE YOU SET THE SECOND CONTROLLER
               child: Container(
                  //TODO: add your content here
               ),
             )
        ],
    ),
 );
}
}
import'包装:flift/cupertino.dart';
类MyHomePage扩展StatefulWidget{
@凌驾
_MyHomePageState createState()=>\u MyHomePageState();
}
类_MyHomePageState扩展状态{
ScrollController firstScroll=ScrollController();
ScrollController第二个ScrollController=ScrollController();
@凌驾
void initState(){
super.initState();
firstScroll.addListener((){
//这在触发滚动时调用,
第二滚动控制器
.jumpTo(firstScroll.offset);//这将同步滚动;
});
secondScrollController.addListener((){
//这在触发滚动时调用,
第一卷
.jumpTo(secondScrollController.offset);//这将同步滚动;
});
}
@凌驾
小部件构建(构建上下文){
返回容器(
子:列(
儿童:[
SingleChildScrollView(
//这是第一卷
滚动方向:轴水平,
控制器:firstScroll,//这是第一个滚动控制器
子:容器(
//TODO:在此处添加您的内容
),
),
SingleChildScrollView(
滚动方向:轴水平,
控制器:第二控制器,
//这里设置第二个控制器
子:容器(
//TODO:在此处添加您的内容
),
)
],
),
);
}
}

这是因为每次调用
jumpTo
方法时,它都会调用第一个方法,第一个方法调用第二个方法,这样就会有一个无限循环

解决方案是您使用自己的ScrollController方法创建自己的ScrollController,以便在不发出通知的情况下跳转到另一个位置

这是您可以创建的自定义滚动控制器:

            class CustomScrollController extends ScrollController {
              CustomScrollController({
                double initialScrollOffset = 0.0,
                keepScrollOffset = true,
                debugLabel,
              }) : super(
                        initialScrollOffset: initialScrollOffset,
                        keepScrollOffset: keepScrollOffset,
                        debugLabel: debugLabel);

              @override
              _UnboundedScrollPosition createScrollPosition(
                ScrollPhysics physics,
                ScrollContext context,
                ScrollPosition oldPosition,
              ) {
                return _UnboundedScrollPosition(
                  physics: physics,
                  context: context,
                  oldPosition: oldPosition,
                  initialPixels: initialScrollOffset,
                );
              }

              void jumpToWithoutGoingIdleAndKeepingBallistic(double value) {
                assert(positions.isNotEmpty, 'ScrollController not attached.');
                for (_UnboundedScrollPosition position
                    in new List<ScrollPosition>.from(positions))
                  position.jumpToWithoutGoingIdleAndKeepingBallistic(value);
              }
            }

            class _UnboundedScrollPosition extends ScrollPositionWithSingleContext {
              _UnboundedScrollPosition({
                ScrollPhysics physics,
                ScrollContext context,
                ScrollPosition oldPosition,
                double initialPixels,
              }) : super(
                      physics: physics,
                      context: context,
                      oldPosition: oldPosition,
                      initialPixels: initialPixels,
                    );

              /// There is a feedback-loop between aboveController and belowController. When one of them is
              /// being used, it controls the other. However if they get out of sync, for timing reasons,
              /// the controlled one with try to control the other, and the jump will stop the real controller.
              /// For this reason, we can't let one stop the other (idle and ballistics) in this situation.
              void jumpToWithoutGoingIdleAndKeepingBallistic(double value) {
                if (pixels != value) {
                  forcePixels(value);
                }
              }
            }
类CustomScrollController扩展了ScrollController{
自定义滚动控制器({
双初始滚动偏移=0.0,
keepscroloffset=true,
调试标签,
}):超级(
initialScrollOffset:initialScrollOffset,
keepscroloffset:keepscroloffset,
debugLabel:debugLabel);
@凌驾
_无界CrollPosition CreateCrollPosition(
物理,,
滚动上下文上下文,
滚动位置oldPosition,
) {
返回_无界CrollPosition(
物理学:物理学,
上下文:上下文,
oldPosition:oldPosition,
initialPixels:initialScrollOffset,
);
}
无效跳转,无需跳转并保持弹道(双值){
断言(positions.isNotEmpty,“ScrollController未连接”);
对于(_)无界CrollPosition位置
在新列表中。从(位置))
位置。跳到无引线且保持弹道(值);
}
}
类_UnboundedScrollPosition使用SingleContext扩展ScrollPosition{
_无界CrollPosition({
物理,,
滚动上下文上下文,
滚动位置oldPosition,
双初始像素,
}):超级(
物理学:物理学,
上下文:上下文,
oldPosition:oldPosition,
初始像素:初始像素,
);
///上面的控制器和下面的控制器之间有一个反馈回路。当其中一个控制器
///在使用时,它控制另一个。但是,如果由于时间原因,它们不同步,
///被控制的一方试图控制另一方,跳转将停止真正的控制器。
///因此,在这种情况下,我们不能让一方阻止另一方(空转和弹道)。
无效跳转,无需跳转并保持弹道(双值){
如果(像素!=值){
像素(值);
}
}
}
只需调用
jumptow而不使用dle并保持弹道
,而不是
jumptow

这里有一个工作示例:

结果


谢谢您的解决方案,但如果我尝试这样做,反弹效果将丢失,列表甚至会出现空白。(即…,超过范围)添加了有问题的图像。shrinkWrap:是的,请删除列表的反弹效果,如果删除该值,您的布局可能会出现一些问题,试着使用Slivist是一个单子滚动控制器,我们希望反弹效果符合要求抱歉,我更新了我的代码:再次检查->不工作,伙计。弹跳效果不出现,滚动不自由。它在抽搐。