Search code examples
fluttertabstabbarscrollableflutter-pageview

flutter scollable.ensurevisible not working in reverse direction


Please check the video / gif:

enter image description here

I have a pageview that will make the current tab active. I need to ensure the active tab is always visible even if the user swipes the screen multiple times. It is working from the left to right. But when we try back from right to left it's not behaving as expected.

PageView file

         PageView(
            controller: pageController,
            onPageChanged: (int page) {
              _duaWidgetState.currentState.updateBtn(page + 1);
              Scrollable.ensureVisible(
                  _duaWidgetState.currentState.activeBtn.currentContext);
            },
            children: loaded

TabBarWidget with scroll view file

    GlobalKey activeBtn = GlobalKey();
      var _selectedTab = 1;
      @override
      Widget build(BuildContext context) {
        return Container(
          padding: EdgeInsets.symmetric(vertical: 20),
          child: SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            child: Row(
              children: List.generate(widget.numberOfTab,
                  (index) => tabBarItem(index + 1, widget.numberOfTab, activeBtn)),
            ),
          ),
        );
      }

Container that uses the Key

               Container(
                  key: activeBtn,
                  margin: EdgeInsets.only(left: 20),
                  padding: EdgeInsets.symmetric(
                    vertical: 10,
                    horizontal: 24,
                  ),


Solution

  • No One answered my Question. But, after a lot of effort and time. I found a workaround to fix this problem. Hope this is a bug and will fix by the flutter team in the coming updates.

    Scrollable.ensureVisible(_duaWidgetState.currentState.activeBtn.currentContext); 
    

    This function has an optional argument called alignment which can be adjusted to make sure the selected element/button is in the center of the viewport. (In my case horizontally center).

    My widgets are horizontally scrollable, so I need to update the page number according to the result from PageView(), Here when I used

    alignment: 0
    

    Its working fine from left to right swipes of page view. But with this alignment when i swipe page from right to left to go to previous page in the PageView widget, the ensureVisible is not working like expected. The selected element/button is out of the view. I experimented and found that when I used

    aligment: 1
    

    The ensureVisible is working fine from the swipes from right to left but at the same time. when I scroll left to right the same problem occured.

    Finally, so I managed to do some workaround to fix this behavior. The solution is to store last page index in a variable and check whether the last page is greater than the new page then alignment: 0 and if the last page less than the new page aligment:1 like that.

       PageView(
        onPageChanged: (int page) {
        if (lastPage < page) {
        Scrollable.ensureVisible(
        _duaWidgetState.currentState.activeBtn.currentContext,
         
         alignment: -0.0100,
         );
         } else {
         Scrollable.ensureVisible(
            _duaWidgetState.currentState.activeBtn.currentContext,
                            (Perfect For font size 24)
         alignment: 1.005,
                        );
                      }}
    

    Hope my answer will help someone in the future.