Search code examples
androidiosflutterdartflip

How to turn the page back and forth with flutter flip_page widget?


I am making a book reading page with Flutter and I added 10 pages as images, the code has a page turning animation. but this animation only turns the pages forward, I want it to turn backwards and I want to be able to navigate back and forth between pages. I'am did try chat gpt :D for it but not work, how do I do this?

import 'package:flutter/material.dart';
import 'package:flip_widget/flip_widget.dart';
import 'dart:math' as math;

class AchristmasCarol extends StatefulWidget {
  @override
  _AchristmasCarolState createState() => _AchristmasCarolState();
}

const double _MinNumber = 0.008;

double _clampMin(double v) {
  if (v < _MinNumber && v > -_MinNumber) {
    if (v >= 0) {
      v = _MinNumber;
    } else {
      v = -_MinNumber;
    }
  }
  return v;
}

class _AchristmasCarolState extends State<AchristmasCarol> {
  GlobalKey<FlipWidgetState> _flipKey = GlobalKey();

  Offset _oldPosition = Offset.zero;
  bool _visible = true;

  List<String> pages = [
    'assets/pics/A Christmas Carol.jpg',
    'assets/books/A Christmas Carol/page 1.png',
    'assets/books/A Christmas Carol/page 2.png',
    'assets/books/A Christmas Carol/page 3.png',
    'assets/books/A Christmas Carol/page 4.png',
    'assets/books/A Christmas Carol/page 5.png',
    'assets/books/A Christmas Carol/page 6.png',
    'assets/books/A Christmas Carol/page 7.png',
    'assets/books/A Christmas Carol/page 8.png',
    'assets/books/A Christmas Carol/page 9.png',
    'assets/books/A Christmas Carol/page 10.png',
    // Add more pages as needed
  ];

  int currentPageIndex = 0;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    Size screenSize = MediaQuery.of(context).size;
    Size boxSize = Size(screenSize.width, screenSize.height);

    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Visibility(
                child: Container(
                  width: boxSize.width,
                  height: boxSize.height,
                  child: GestureDetector(
                    child: FlipWidget(
                      key: _flipKey,
                      textureSize: boxSize * 3,
                      child: Container(
                        color: Color.fromARGB(255, 255, 255, 255),
                        child: Center(
                          child: Image.asset(
                            pages[currentPageIndex],
                            fit: BoxFit.cover,
                          ),
                        ),
                      ),
                    ),
                    onHorizontalDragStart: (details) {
                      _oldPosition = details.globalPosition;
                      _flipKey.currentState?.startFlip();
                    },
                    onHorizontalDragUpdate: (details) {
                      Offset off = details.globalPosition - _oldPosition;
                      double tilt = 1 / _clampMin((-off.dy + 20) / 100);
                      double percent =
                          math.max(0, -off.dx / boxSize.width * 1.4);
                      percent = percent - percent / 2 * (1 - 1 / tilt);
                      _flipKey.currentState?.flip(percent, tilt);
                    },
                    onHorizontalDragEnd: (details) {
                      _flipKey.currentState?.stopFlip();
                      _updatePageIndex();
                    },
                    onHorizontalDragCancel: () {
                      _flipKey.currentState?.stopFlip();
                    },
                  ),
                ),
                visible: _visible,
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _updatePageIndex() {
    setState(() {
      if (currentPageIndex < pages.length - 1) {
        currentPageIndex++;
      } else {
        currentPageIndex = 0;
      }
    });
  }
}

Solution

  • In _updatePageIndex method you are setting the pageIndex as increments or 0 but never reducing the page number (decrement).

    Instead you can use this package

    page_flip

    it has both forward and backward flips

    PageFlipWidget(
            key: _controller,
            backgroundColor: Colors.white,
            // isRightSwipe: true,
            lastPage: Container(color: Colors.white, child: const Center(child: Text('Last Page!'))),
            children: <Widget>[
              for (var i = 0; i < 10; i++) DemoPage(page: i),
            ],
          )