Scrolling in both directions (Right to Left <=> Left to Right) with Flutter PageView widget

75 Views Asked by At

I'm using 'PageView' widget in flutter to show a list of images horizontally - one image at a time; I've implemented below code and it works fine but it won't scroll when trying to scroll from right-to-left and index is at 0 as the widget is built to work in a single direction by default.

I tried to reverse the scrolling direction with the 'reverse' parameter programmatically while the user is doing the swiping gestures but couldn't figure it out.

import 'package:flutter/material.dart';
import 'package:qurani_piroz/Files/Functions.dart' as funcs;
import 'package:qurani_piroz/Files/Constants.dart' as consts;
import 'package:qurani_piroz/Services/Themes/Themes_Model.dart';
import 'package:qurani_piroz/Services/Widget_Size_Configuration/size_config.dart';

class getImagesSlides extends StatefulWidget {
  const getImagesSlides({super.key});

  @override
  State<getImagesSlides> createState() => _getImagesSlidesState();
}

class _getImagesSlidesState extends State<getImagesSlides> {
  late PageController myImagesController;
  late ValueNotifier<int> picIndexNotifier;
  late ValueNotifier<bool> isReverseNotifier;

  @override
  void initState() {
    super.initState();
    picIndexNotifier = ValueNotifier<int>(0);
    isReverseNotifier = ValueNotifier<bool>(false);
    myImagesController = PageController(
      initialPage: 1,
      viewportFraction: 1.0,
    );
    WidgetsBinding.instance.addPersistentFrameCallback((timeStamp) {
      checkPageView();
    });
  }

  checkPageView() {
    myImagesController.addListener(() {});
  }

  @override
  void dispose() {
    picIndexNotifier.dispose();
    isReverseNotifier.dispose();
    myImagesController.dispose();
    super.dispose();
  }

  int getPicIndex(int picIndex, int picsCount) {
    return picIndex % picsCount;
  }

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
        valueListenable: isReverseNotifier,
        builder: (context, isReverseValue, _) {
          return Container(
            height: deviceVerticalSize * 25,
            width: double.infinity,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(
                consts.mainBorderRadius,
              ),
              color: context.theme.colorScheme.onPrimary,
            ),
            margin: EdgeInsets.fromLTRB(
              consts.leftSideMargin,
              0,
              consts.rightSideMargin,
              0,
            ),
            child: Center(
              child: PageView.builder(
                pageSnapping: true,
                reverse: isReverseValue,
                controller: myImagesController,
                onPageChanged: (int newPicIndex) {
                  funcs.printout_to_console('pageview - index - $newPicIndex');
                  picIndexNotifier.value = newPicIndex;
                },
                itemBuilder: (context, picIndex) {
                  return GestureDetector(
                    onTap: () {
                      //
                    },
                    child: SizedBox(
                      width: deviceHorizantalSize * 69,
                      child: Column(
                        children: [
                          Stack(
                            children: [
                              Image.asset(
                                'assets/images/pic5.png',
                                height: deviceVerticalSize * 25,
                              ),
                            ],
                          ),
                        ],
                      ),
                    ),
                  );
                },
              ),
            ),
          );
        });
  }
}

I also tried using the 'controller.addListener(() {})' method to detect when the 'PageView' widget is being used - it detects normally on the specified scrolling direction only so at index 0 and scrolling on reverse direction then the 'addListender' won't detect anything.

Any suggestion regarding how to achieve this would be appreciated.

1

There are 1 best solutions below

4
MendelG On

To scroll backwards, even if the index is at 0, you can use the loop_page_view package:

import 'package:flutter/material.dart';
import 'package:loop_page_view/loop_page_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Loop Page View Demo'),
        ),
        body: Center(
          child: LoopPageView.builder(
            itemCount: 10,
            itemBuilder: (_, index) {
              return Card(
                child: Center(
                  child: Text('$index'),
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}

Result

enter image description here