滚动列表取决于另一个滚动列表 Flutter

Scroll list depending on another list scrolling Flutter

提问人:Jaafar Melhem 提问时间:6/15/2022 最后编辑:Md. Yeasin SheikhJaafar Melhem 更新时间:6/16/2022 访问量:607

问:

例如,我如何根据另一个列表滚动来滚动列表:

class ConectLists extends StatefulWidget {
  const ConectLists({Key? key}) : super(key: key);

  @override
  State<ConectLists> createState() => _ConectListsState();
}

class _ConectListsState extends State<ConectLists> {
  ScrollController scrollConroller1 = ScrollController();
  ScrollController scrollConroller2 = ScrollController();
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    scrollConroller1.dispose();
    scrollConroller2.dispose();

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          SizedBox(
            height: 8,
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Text('List 1'),
              Text('List 2'),
            ],
          ),
          SizedBox(
            height: 8,
          ),
          Container(
            color: Colors.black.withOpacity(0.5),
            width: double.infinity,
            height: 4,
          ),
          Expanded(
            child: Row(
              children: [
                Expanded(
                  flex: 1,
                  child: ListView.builder(
                    controller: scrollConroller1,
                    itemBuilder: (context, index) => Card(
                        elevation: 3,
                        child: SizedBox(
                            height: 40,
                            child:
                                Center(child: Text('First list item $index')))),
                    itemCount: 50,
                  ),
                ),
                Container(
                  color: Colors.black.withOpacity(0.5),
                  width: 4,
                  height: double.infinity,
                ),
                Expanded(
                  child: ListView.builder(
                    controller: scrollConroller2,
                    itemBuilder: (context, index) => Card(
                        elevation: 3,
                        child: SizedBox(
                            height: 40,
                            child: Center(
                                child: Text('Second list item $index')))),
                    itemCount: 25,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

例如,当 List1 滚动时,我需要使列表 2 滚动,并控制 list2 滚动的速度(不同的滚动速度)或反转方向。

在 Fultter 中有一种简单的方法可以做到这一点吗?

enter image description here

flutter dart flutter-layout flutter-listview

评论


答:

2赞 esentis 6/15/2022 #1

您可以通过将听众添加到您的喜欢中来轻松实现这一点,因此:ScrollController

controller: scrollConroller1..addListener(() {
 scrollConroller2.animateTo(scrollConroller1.offset,
 curve: Curves.easeInOut,
 duration: const Duration(milliseconds: 450));
}),

基本上,您监听滚动更改,然后将滚动更改分配给另一个列表。但是,当第一个列表的长度大于第二个列表时,第二个列表将继续在底部反弹(在 iOS 设备上)。您可以通过检查第一个列表的偏移量是否大于第二个列表的偏移量来解决此问题:OffsetmaxScrollExtent

controller: scrollConroller1..addListener(() {
 if (scrollConroller1.offset <= scrollConroller2.position.maxScrollExtent){
  scrollConroller2.animateTo(scrollConroller1.offset,
  curve: Curves.easeInOut,
  duration: const Duration(milliseconds: 450));
 }
}),

评论

0赞 Jaafar Melhem 6/15/2022
非常感谢,此解决方案运行良好。有没有办法降低成本?第一次和第二次滚动之间有明显的时间延迟,是否可以使用相同的控制器控制两个列表,但每个列表的行为不同?
2赞 Alessandro Vendrame 6/15/2022
@JaafarMelhem尝试在 Duration 中放入另一个值。例如:const 持续时间(微秒:1)
2赞 Alessandro Vendrame 6/15/2022
@JaafarMelhem或代替使用“animateTo”,您应该尝试使用“jumpTo”方法。
0赞 Jaafar Melhem 6/16/2022
也许这是唯一的解决方案。我需要使第二个列表滚动速度比第一个列表慢,因此当第一个列表到达终点时,第二个列表在同一时间到达终点,即第二个列表滚动与第一个列表滚动,但速度慢一半,并且移动平稳,不显示跳跃和时间延迟与第一个列表交互, 非常感谢,感谢您的帮助
2赞 Tonny Bawembye 6/15/2022 #2

您可以在初始化状态下添加一个侦听器,使 scrollConroller2 跳转到 scrollConroller1 所在的位置,如下所示。

感谢 esentis 在第一个列表的偏移量较大时进行修复 比第二个列表的 maxScrollExtent :

@override
  void initState() {
    super.initState();
    //Your other code in init state
    scrollConroller1.addListener(() {
      if (scrollConroller1.offset <=
          scrollConroller2.position.maxScrollExtent) {
        setState(() {
          double value2 = scrollConroller1.offset;
          scrollConroller2.jumpTo(value2);
        });
      }
    });
  }

若要反向滚动,可以将侦听器设置为:

scrollConroller1.addListener(() {
      if (scrollConroller1.offset <=
          scrollConroller2.position.maxScrollExtent) {
        setState(() {
          double value2 = scrollConroller2.position.maxScrollExtent -
              scrollConroller1.offset;
          scrollConroller2.jumpTo(value2);
        });
      }
    });
1赞 Md. Yeasin Sheikh 6/16/2022 #3

要控制列表滚动,同时保持基于高度比的滚动偏移量,因此跳转偏移量将是

jumpPoss = (math.min(l1maxHeight, l2maxHeight) * scrollOffset) /
          math.max(l1maxHeight, l2maxHeight);
   late ScrollController scrollController1 = ScrollController()
    ..addListener(() {
      double scrollOffset = scrollController1.offset;

      final double l1maxHeight = scrollController1.position.maxScrollExtent;
      final double l2maxHeight = scrollController2.position.maxScrollExtent;

      double jumpPoss = (math.min(l1maxHeight, l2maxHeight) * scrollOffset) /
          math.max(l1maxHeight, l2maxHeight);
      scrollController2.jumpTo((jumpPoss));
    });

如果您需要停止滚动最大限制,您可以按照 @Tonny Bawembye 的答案进行操作。