Search code examples
flutterdartflutter-state

ListWheelScrollViewX won't scroll to start


I have a StatefulWidget with a ListWheelScrollViewX in it. What I want to achive is whan the callback function setHeight is called I need to scroll the widget to the start.

class HeightWidget extends StatefulWidget {
      const HeightWidget(
          {required this.setHeight, required this.initialHeight, super.key});
    
      final Function(double) setHeight;
      final int initialHeight;
    
      @override
      State<HeightWidget> createState() => _HeightWidgetState();
    }
    
    class _HeightWidgetState extends State<HeightWidget> {
      List<Widget> elements = [];
    
      void fillWidget() {
        for (int i = 0; i < 230; i++) {
          elements.add(
            Align(
              alignment: Alignment.center,
              child: Text(
                i.toString(),
              ),
            ),
          );
        }
      }
    
      void setElement(int index) {
        widget.setHeight(index.toDouble() + 60);
      }
    
      @override
      void initState() {
        fillWidget();
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
          margin: const EdgeInsets.all(10.0),
          padding: const EdgeInsets.all(3.0),
          decoration: BoxDecoration(
            border: Border.all(color: Colors.black),
            borderRadius: const BorderRadius.all(
              Radius.circular(15.0),
            ),
          ),
          child: Column(
            children: [
              const SizedBox(
                height: 10.0,
              ),
              const HeaderWidget(title: "Height (in cm)"),
              Container(
                margin: const EdgeInsets.all(10.0),
                padding: const EdgeInsets.all(3.0),
                decoration: const BoxDecoration(
                  color: kWeightBackgroundColor,
                  borderRadius: BorderRadius.all(
                    Radius.circular(25.0),
                  ),
                ),
                child: SizedBox(
                  height: 100,
                  child: ListWheelScrollViewX(
                    scrollDirection: Axis.horizontal,
                    physics: const FixedExtentScrollPhysics(),
                    controller: FixedExtentScrollController(
                        initialItem: widget.initialHeight),
                    itemExtent: 40,
                    onSelectedItemChanged: (int index) {
                      setElement(index);
                    },
                    magnification: 1.5,
                    useMagnifier: true,
                    children: elements,
                  ),
                ),
              ),
            ],
          ),
        );
      }
    }

I've tried in a lot of ways but it wont scroll to 0. Do you have any suggestion? At the parent widget this function is called by the callback:

  void updateHeight() {
    setState(() {
      _initialHeight = 0;
    });
  }

Solution

  • You can change Current scroll offset by using a ScrollController

    enter image description here

    Just define a scrollController and use it when you need:

      Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            child: Text('Set Scroll point to 0'),
            onPressed: () {
              scrollController.animateTo(0,
                  duration: Duration(milliseconds: 200),
                  curve: Curves.bounceIn);
            },
          ),
          ElevatedButton(
            child: Text('Set Scroll last point'),
            onPressed: () {
              scrollController.animateTo(
                  scrollController.positions.last.maxScrollExtent,
                  duration: Duration(milliseconds: 200),
                  curve: Curves.bounceIn);
            },
          )
        ],
      )
    

    Here's the full example:

    class _MyWidgetState extends State<MyWidget> {
      var scrollController = ScrollController();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(),
            body: Column(children: [
              Text('Minutes List Wheel Scroll View'),
              Expanded(
                child: ListWheelScrollView(
                  children: [
                    for (int i = 1; i < 61; i++)
                      Text(
                        i.toString(),
                      )
                  ],
                  itemExtent: 20,
                  magnification: 20,
                  controller: scrollController,
                ),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  ElevatedButton(
                    child: Text('Set Scroll point to 0'),
                    onPressed: () {
                      scrollController.animateTo(0,
                          duration: Duration(milliseconds: 200),
                          curve: Curves.bounceIn);
                    },
                  ),
                  ElevatedButton(
                    child: Text('Set Scroll last point'),
                    onPressed: () {
                      scrollController.animateTo(
                          scrollController.positions.last.maxScrollExtent,
                          duration: Duration(milliseconds: 200),
                          curve: Curves.bounceIn);
                    },
                  )
                ],
              )
            ]));
      }
    }