14

when multiple instances of widget are rendered and the getValue method is called flutter throws the error ScrollController attached to multiple scroll views. I'm assuming this is because they all are using the same controller but I don't know a way to fix this without creating a separate widget for each time it is used. Is there a better way to fix this?

class NumScroller extends StatelessWidget{
  final int max,min;
  final double height,width;
  final TextAlign alignment;

  static ScrollController controller;

  NumScroller({this.height,this.width,this.alignment,this.min,this.max, initialOffset}){
    controller = new ScrollController(initialScrollOffset: initialOffset);
  }

  getValue() => (controller.offset~/height) + min;

  @override
  Widget build(BuildContext context) {
    return new Container(
        width: width,
        height: height,
        child: ListView.builder(itemBuilder: (context, index) {
          return new Container(height: height, child:Text((max - index).toString(),textAlign: alignment,));
          },
          itemCount: max - min+1,
          controller: controller,
          physics: PageScrollPhysics(),
          itemExtent: height,
        )
    );
  }

}
6
  • 2
    You should use a stateful widget instead of stateless. Commented Sep 24, 2018 at 17:47
  • Hi @Remi, why this should be Stateful?. Commented Sep 24, 2018 at 18:14
  • 1
    Because then you can have one controller per instance of the widget. Not one static controller used everywhere. Commented Sep 24, 2018 at 18:19
  • Sorry I didn't understand. Even with Stateless we can have one controller per instance of the widget Commented Sep 24, 2018 at 18:25
  • 1
    @DineshBalasubramanian The controller should be kept. Recreating a new one every time a props change (which is what happens when using StatelessWidget) has undesired effects. Commented Sep 24, 2018 at 18:28

4 Answers 4

11

As you are telling when multiple instances are rendered, you are getting this error. When your ScrollController is multiple(one for one view), you will not get any problem. But you have only one ScrollController (because you have static).

Remove the static and it should work.

Please lemme know if it didn't work.

Sign up to request clarification or add additional context in comments.

5 Comments

yeah it worked. I didn't know the solution would be that simple
never mind that error just didn't come up because of a different error
I don't know what is going on anymore, now this works
i created like this way for my 3 listview.builder. it shows same error. So i can not track/listen each list scroll. _controller = ScrollController(); _controller.addListener(_scrollListener); _controller2 = ScrollController(); _controller2.addListener(_scrollListener2); _controller3 = ScrollController(); _controller3.addListener(_scrollListener3); @Dinesh - And
I am also facing the same issue even I have separate ScrollController for each page but the problem is occurring when I am navigating to next page and when I am getting back to the previous page but without Navigator.pop() then it is throwing error. otherwise it is working fine when I am getting back by Navigator.pop()
8

Instead of using a static controller, you should have one controller per widget instance.

You cannot store your controller inside a StatelessWidget though (even if the compiler will allow it).

You need a StatefulWidget for that, or else when your widget is updated you will create a new controller again. Leading to weird behaviors.

Here the final code:

class NumScroller extends StatefulWidget{
  final int max,min;
  final double height,width;
  final TextAlign alignment;

  NumScroller({this.height,this.width,this.alignment,this.min,this.max, initialOffset});

  @override
  NumScrollerState createState() {
    return new NumScrollerState();
  }
}

class NumScrollerState extends State<NumScroller> {
  final ScrollController controller = ScrollController();

  getValue() => (controller.offset~/widget.height) + widget.min;

  @override
  Widget build(BuildContext context) {
    return new Container(
        width: widget.width,
        height: widget.height,
        child: ListView.builder(itemBuilder: (context, index) {
          return new Container(height: widget.height, child:Text((widget.max - index).toString(),textAlign: widget.alignment,));
          },
          itemCount: widget.max - widget.min+1,
          controller: controller,
          physics: PageScrollPhysics(),
          itemExtent: widget.height,
        )
    );
  }
}

4 Comments

Maybe this would work but then you can't access the getValue function
What do you mean? You can access to the state of a widget from others if you want to.
how? as far as I know you can only access properties and methods in the stateful widget and not its state
2

I had some screens in a bottomNavigationBar and I solved adding a key to the widget with the problem.

key: GlobalKey(debugLabel: 'unique_widget_key'),

Comments

0

I faced the same problem where I got the error:
"ScrollController attached to multiple scroll views"

The solution that worked for me:
I simply replaced Get.back() with Navigator.pop(context) — and that fixed the issue.

After looking into it, I realized that the error was caused because my ScrollController was still attached when the screen was popped — maybe cause GetX keeps the controller alive even after navigation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.