scroll_restore

pub package GitHub Workflow Status License: MIT

scroll_restore is a tiny Flutter package that automatically saves and restores the scroll position of any scrollable widget—across rebuilds, hot reloads, navigation pops/pushes, and even app restarts. No boilerplate, no manual state management: just wrap your ListView, GridView, or any scrollable, and it “just works.”


🎯 Features

  • ✅ Persist scroll offset using SharedPreferences
  • ✅ Restore position on init (clamps if content is shorter)
  • ✅ Simple, one-widget API
  • ✅ Zero external dependencies (except shared_preferences)
  • ✅ Compatible with mobile, web, and desktop Flutter apps

📦 Installation

dependencies:
  flutter:
    sdk: flutter

  scroll_restore: ^0.1.0


Then run:


flutter pub get
🚀 Quick Start
Wrap your scrollable in ScrollRestore, giving it a unique id:


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

class ChatScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Chat')),
      body: ScrollRestore(
        id: 'chat_screen_list',  // unique key per scrollable
        builder: (context, controller) {
          return ListView.builder(
            controller: controller,
            itemCount: messages.length,
            itemBuilder: (_, index) {
              return ListTile(
                title: Text(messages[index].text),
              );
            },
          );
        },
      ),
    );
  }
}
id: persisted key in SharedPreferences. Use a different id for each scrollable you want to remember.

The package takes care of saving .offset on every scroll and jumping to it on next build.

📖 Example
A full example app lives in the example/ folder:

cd example
flutter pub get
flutter run
Try scrolling halfway, hot-reloading, navigating away/back, or restarting the app—you’ll stay at the same scroll position!

🧪 Testing
To run the package’s unit & widget tests:

flutter test

⚙️ CI
We use GitHub Actions to:

flutter analyze

flutter test (package & example)

Workflow file: .github/workflows/dart.yml

🛠️ Caveats & Tips
If the saved offset exceeds the new content’s max scroll, it’s clamped to the end.

Works with any ScrollController-driven widget: ListView, GridView, CustomScrollView, etc.

You can nest multiple ScrollRestore widgets on one screen by using different ids.

📜 Changelog
0.1.0
Initial release with basic save & restore logic

Supports clamp-to-boundary and async init

📝 License
MIT © Paul Thommithazhe

Libraries

scroll_restore