Home > Enterprise >  Scroll list depending on another list scrolling Flutter
Scroll list depending on another list scrolling Flutter

Time:06-16

How I can make the scroll of a list depending on another list scrolling for example :

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,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

I need to make list 2 scroll when List1 scroll with controlling the speed of the list2 scrolling (different scroll speed) for example or reverse the direction for example..

Is there a lite way to do this in Fultter ?

enter image description here

CodePudding user response:

You can easily achieve this by adding listeners to your ScrollController like so :

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

Basically you listen on scroll changes and you assign ones' Offset to the other list. However, when the first list's length is larger than the second list,the second list will keep on bouncing at the bottom (on iOS devices). You could fix that by checking if the first list's offset is larger than the second list's maxScrollExtent :

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

CodePudding user response:

To control list scroll while maintaining the scroll offset that will be based on height ratio, Therefore the jump offset will be

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));
    });

You can follow @Tonny Bawembye's answer if you need to stop scrolling on max limit.

CodePudding user response:

You could add a listener in your init state to make scrollConroller2 jump to the postion scrollConroller1 is at as below.

Credit to esentis for the fix when first list's offset is larger than the second list's 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);
        });
      }
    });
  }

To scroll in reverse, you can set the listener instead to:

scrollConroller1.addListener(() {
      if (scrollConroller1.offset <=
          scrollConroller2.position.maxScrollExtent) {
        setState(() {
          double value2 = scrollConroller2.position.maxScrollExtent -
              scrollConroller1.offset;
          scrollConroller2.jumpTo(value2);
        });
      }
    });
  • Related