ScrollController jumpTo specified value doesn't work Flutter

2.4k views Asked by At

In my app I decided to show a ScrollBar so as the same ScrollController is needed both in the ScrollBar and the ListView I had to change my ScrollablePositionedList.builder to a ListView.builder. First in my List<Widget> homePageItems is a PageView (so at index 0) with some "slides", and then other widgets "content" that are the explanation of the slides. In each slides there is a button which calls controller.jumpTo(); to go to the slide's explanation. When I was using the ScrollablePositionedList.builder the scrollController.jumpTo(index: 5); was working as expected jumping to the right "content" but with ListView.builder it doesn't..it all just move a few pixel and that's it.. Is there something I'm setting wrong or missing to set up now with ListView.builder?

The ListView items:

List<Widget> homePageItems = [
      // carousell index 0
      SizedBox(
        height: MediaQuery.of(context).size.height > 700 ? MediaQuery.of(context).size.height * 0.89 : MediaQuery.of(context).size.height * 0.85,//580,
        width: MediaQuery.of(context).size.width,
        child: Stack(
          alignment: AlignmentDirectional.center,
          children: [
            Column(
              children: [
                Expanded(
                  child: PageView.builder(

                      controller: pageController,
                      onPageChanged: (index) {
                        timer.cancel();
                        setState(() {
                          if (index > _index) {
                            _current < slides.length -1 ? _current++ : _current = 0;
                            _index = index;
                          } else {
                            _current > 0 ? _current -- : _current = slides.length -1;
                            _index = index;
                          }
                          print('onPageChanged: index is : $index');
                          print('onPageChanged: _current is : $_current');
                        });
                      },
                      itemBuilder: (context, index){
                        return slides[_current];
                      }),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: slides.map((url) {
                    int index = slides.indexOf(url);
                    return Container(
                      width: 5.0,
                      height: 5.0,
                      margin: EdgeInsets.symmetric(vertical: 5.0, horizontal: 2.0),
                      decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: _current == index
                            ? Colors.redAccent//Color.fromRGBO(0, 0, 0, 0.9)
                            : Colors.black54,//Color.fromRGBO(0, 0, 0, 0.4),
                      ),
                    );
                  }).toList(),
                ),
              ],
            ),
            Row(
              children: [
                IconButton(
                    icon: Icon(CupertinoIcons.back,color:Colors.white.withAlpha(170),size: 40,),
                    onPressed: (){
                      timer.cancel();
                      pageController.previousPage(duration: Duration(milliseconds: 800), curve: Curves.fastOutSlowIn);
                    }),
                IconButton(
                    icon: Icon(CupertinoIcons.forward,color: Colors.white.withAlpha(150),size: 40,),
                    onPressed: () {
                      timer.cancel();
                      pageController.nextPage(duration: Duration(milliseconds: 800), curve: Curves.fastOutSlowIn);
                    }),
              ],
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
            ),
          ],
        ),
      ),
      // Cloud Biking index 1
      SizedBox(
        height: MediaQuery.of(context).size.height > 700
            ? MediaQuery.of(context).size.height * 0.89
            : 700,//MediaQuery.of(context).size.height * 0.90,//580,
          width: MediaQuery.of(context).size.width,
        child: CloudBikingContent(key: widget.key,)
      ),
      // Stolen bicycles index 2
      SizedBox(
        height: MediaQuery.of(context).size.height > 700
            ? MediaQuery.of(context).size.height * 0.95
            : 800,//MediaQuery.of(context).size.height * 0.90,//580,
        width: MediaQuery.of(context).size.width,
        child: StolenBicyclesContent(key: widget.key),
      ),
      // Scheduler index 3
      SizedBox(
        height: MediaQuery.of(context).size.height > 700

            ? MediaQuery.of(context).size.height * 0.89 // Web
            : 870,//MediaQuery.of(context).size.height * 0.90,//580, // Mobile
        width: MediaQuery.of(context).size.width,
        child: SchedulerContent(key: widget.key,),
      ),
      // Orders index 4
      SizedBox(
        height: MediaQuery.of(context).size.height > 700
            ? MediaQuery.of(context).size.height * 0.89
            : 850,//MediaQuery.of(context).size.height * 0.90,//580,
        width: MediaQuery.of(context).size.width,
        child: OrdersContent(key: widget.key,),
      ),
      // Bookings index 5
      SizedBox(
        height: MediaQuery.of(context).size.height > 700
            ? MediaQuery.of(context).size.height * 0.89
            : 850,//MediaQuery.of(context).size.height * 0.90,//580,
        width: MediaQuery.of(context).size.width,
        child: BookingsContent(key: widget.key),
      ),
      NavigationBarBottom()
    ];

The PageView items:

List<Widget> slides = [
    ScreenTypeLayout(
      mobile: CloudBikingSlideMobile(
          bgImage: mainBgImageMobile,
      onTap: (){
        controller.jumpTo(1);
//        scrollController.jumpTo(index: 1);
//            scrollController.scrollTo(index: 1, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);// .jumpTo(index: 1);
      }),
      desktop: CloudBikingSlideDesktop(
        bgImage: mainBgImageDesktop,
        onTap: (){
          controller.jumpTo(1);
//          scrollController.jumpTo(index: 1);
//          scrollController.scrollTo(index: 1, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 1);
        }),
    ),
    ScreenTypeLayout(
      mobile: StolenBicyclesSlideMobile(
          bgImage: stolenBicyclesBgMobile,
        onTap: (){
          controller.jumpTo(2);
//            scrollController.jumpTo(index: 2);
//          scrollController.scrollTo(index: 2, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 2);
        }),
      desktop: StolenBicyclesSlideDesktop(
          bgImage: stolenBicyclesBgDesktop,
        onTap: (){
          controller.jumpTo(2);
//          scrollController.jumpTo(index: 2);
//          scrollController.scrollTo(index: 2, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 2);
        }),
    ),
    ScreenTypeLayout(
      mobile: SchedulerSlideMobile(
        bgImage: schedulerBgImageMobile,
        onTap: (){
          controller.jumpTo(3);
//          scrollController.jumpTo(index: 3);
//          scrollController.scrollTo(index: 3, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 3);
        }),
      desktop: SchedulerSlideDesktop(
        bgImage: schedulerBgImageDesktop,
    onTap: (){
      controller.jumpTo(3);
//      scrollController.jumpTo(index: 3);
//    scrollController.scrollTo(index: 3, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 3);
    }),
    ),
    ScreenTypeLayout(
      mobile: OrdersSlideMobile(
        bgImage: orderBgImageMobile,
          onTap: (){
            controller.jumpTo(4);
//          scrollController.jumpTo(index: 4);
//            scrollController.scrollTo(index: 4, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 4);
          }),
      desktop: OrdersSlideDesktop(
        bgImage: orderBgImageDesktop,
          onTap: (){
            controller.jumpTo(4);
//            scrollController.jumpTo(index: 4);
//            scrollController.scrollTo(index: 4, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 4);
          }),
    ),
    ScreenTypeLayout(
      mobile: BookingsSlideMobile(
        bgImage: bookingBgImageMobile,
          onTap: (){
            controller.jumpTo(5);
//            scrollController.jumpTo(index: 5);
//            scrollController.scrollTo(index: 5, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 5);
          }),
      desktop: BookingsSlideDesktop(
        bgImage: bookingBgImageDesktop,
          onTap: (){
            controller.jumpTo(5);
//            scrollController.jumpTo(index: 5);
//            scrollController.scrollTo(index: 5, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 5);
          }),
    ),
  ];

the ListView:

Scaffold(
      backgroundColor: Colors.transparent,
      body: Container(
        color: Colors.transparent,
      child: Scrollbar(
        controller: controller,
        isAlwaysShown: true,
        thickness: 10,
        radius: Radius.circular(5),
//        child: ScrollablePositionedList.builder(
//            itemScrollController: scrollController,
//            initialScrollIndex: 0,
//            itemCount: homePageItems.length,
//            itemBuilder: (BuildContext context, int index) => homePageItems[index],
        child: ListView.builder(
          controller: controller,
          itemCount: homePageItems.length,
          itemBuilder: (BuildContext context, int index) => homePageItems[index],


          ),
      ),
      ),
    );
1

There are 1 answers

0
Vincenzo On BEST ANSWER

Found the problem. ScrollController's jumpTo is expecting a pixel value while ItemScrollController's jumpTo is expecting an index to jump to and moves accordingly.. actually a better solution IMHO.. So by multiplying the content height by its index you have the right amount of pixel to shift..

double contentHeight = MediaQuery.of(context).size.height > 700 ? MediaQuery.of(context).size.height * 0.89 : MediaQuery.of(context).size.height * 0.85;

...

onTap: (){
          controller.jumpTo(2 * contentHeight);
//          scrollController.jumpTo(index: 2);
//          scrollController.scrollTo(index: 2, duration: Duration(milliseconds: 300), curve: Curves.easeInOut);//.jumpTo(index: 2);
        }
``