Search code examples
androidiosflutterdartdata-processing

How do I ensure that the user continues where they left off in the application in Flutter?


I made a book reading page with the Page_Flip widget, but when the user leaves the application and re-enters the book page, I want it to continue from where it left off. How can I keep the user's information? I tried features such as Onflip, currentPage, but the widget I use does not support them.

// HomeScreen.dart

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

final _controller = GlobalKey<PageFlipWidgetState>();

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

  @override
  State<AChristmasCarol> createState() => _AChristmasCarolState();
}

class _AChristmasCarolState extends State<AChristmasCarol> {
  final List<String> imagePaths = [
    '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
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageFlipWidget(
        key: _controller,
        backgroundColor: Colors.white,
        lastPage: Container(
            color: Colors.white, child: const Center(child: Text('The End!'))),
        children: [
          for (var imagePath in imagePaths) _buildDemoPage(imagePath),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.looks_one_outlined),
        onPressed: () {
          _controller.currentState?.goToPage(1);
        },
      ),
    );
  }

  Widget _buildDemoPage(String imagePath) {
    return Scaffold(
      body: Image.asset(
        imagePath,
        fit: BoxFit.cover,
      ),
    );
  }
}

Solution

  • You can utilise the sharedPreference to store and retrieve the LastLeftOverPageIndex. You can download the library from here

    you have to store the current page number when user exit the application using or navigate to different screen using deactivate method and restore the store the previously stored index when user enter the screen using initState Method;

    I have modified your code

    class BookDemo extends StatefulWidget {
      const BookDemo({super.key});
    
      @override
      State<BookDemo> createState() => _BookDemoState();
    }
    
    class _BookDemoState extends State<BookDemo> {
      final _controller = GlobalKey<PageFlipWidgetState>();
    
      // sharedPreferences to store lastLeftOverPage Index
      final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
    
      // last left over page index
      int lastLeftOverPageIndex = 0;
    
      // SharedPreference key to retrieve the  value of lastLeftOverPageIndex
      String lastLeftOverPageNoPrefKey = "_lastLeftOverPageNoPrefKey";
    
      final List<String> imagesPath = [
        "assets/images/image_1.png",
        "assets/images/image_2.png",
        "assets/images/image_3.png"
      ];
    
      Widget _buildDemoPage(String imagePath) {
        return Scaffold(
          body: Image.asset(
            imagePath,
            fit: BoxFit.cover,
          ),
        );
      }
    
      @override
      void initState() {
        // restore the previous lastLeftOverPageIndex;
        _restoreLeftOverPage();
        super.initState();
      }
    
      Future<void> _restoreLeftOverPage() async {
        SharedPreferences pref = await _prefs;
        lastLeftOverPageIndex =
            pref.getInt(lastLeftOverPageNoPrefKey)?.toInt() ?? 0;
        // navigate the book page index to lastLeftOverPageIndex
        _controller.currentState?.goToPage(lastLeftOverPageIndex);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: PageFlipWidget(
            key: _controller,
            backgroundColor: Colors.white,
            initialIndex: lastLeftOverPageIndex,
            lastPage: Container(
                color: Colors.white, child: const Center(child: Text('The End!'))),
            children: [
              for (var imagePath in imagesPath) _buildDemoPage(imagePath),
            ],
          ),
          floatingActionButton: FloatingActionButton(
            child: const Icon(Icons.looks_one_outlined),
            onPressed: () {
              _controller.currentState?.goToPage(1);
            },
          ),
        );
      }
    
      @override
      void dispose() {
        super.dispose();
      }
    
      @override
      void deactivate() {
    // before disposing the widget save the current page no
        var currentPageNo = _controller.currentState?.pageNumber.toInt() ?? 0;
        saveLastLeftOverPaqePref(currentPageNo);
      }
    
      Future<void> saveLastLeftOverPaqePref(var lastPage) async {
        SharedPreferences pref = await _prefs;
        pref.setInt(lastLeftOverPageNoPrefKey, lastPage);
      }
    }
    

    If my answer worked for you don't forget to mark it.