I want to save an index of PageView
and load it when reopening the app.
For example, if a user closes the app on page 2, the app should be started on page 2.
I tried to implement this feature by using shared_preferences and provider.
However, the app always starts on page 1, probably because PageController
's initialPage
is initialized as 0
. BottomNavigationbar
's BottomNavigationBarItem
works as expected.
How can I save an index of PageView
and load it when a user reopens the app?
main.dart
import 'package:flutter/material.dart';
import 'package:test/home_screen.dart';
import 'package:test/provider_data.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => ProviderData(),
child: MaterialApp(
title: 'test',
home: const HomeScreen(),
),
);
}
}
home_screen.dart
import 'package:flutter/material.dart';
import 'package:test/page1.dart';
import 'package:test/page2.dart';
import 'package:test/provider_data.dart';
import 'package:provider/provider.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final List<Widget> _pageList = const [
Page1(),
Page2(),
];
final PageController _pageController = PageController();
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Consumer<ProviderData>(
builder: (context, providerData, child) {
return PageView(
controller: _pageController,
children: _pageList,
onPageChanged: (index) {
providerData.changePageIndex(index);
},
);
},
),
),
bottomNavigationBar: Consumer<ProviderData>(
builder: (context, providerData, child) {
return BottomNavigationBar(
onTap: (index) {
_pageController.animateToPage(
index,
duration: const Duration(microseconds: 10),
curve: Curves.linear,
);
providerData.changePageIndex(index);
},
type: BottomNavigationBarType.fixed,
currentIndex: providerData.pageIndex!,
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Page 2',
),
],
);
},
),
);
}
}
provider_data.dart
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ProviderData extends ChangeNotifier {
SharedPreferences? prefs;
final String pageIndexKey = 'pageIndex';
int? _pageIndex;
int? get pageIndex => _pageIndex;
ProviderData() {
_pageIndex = 0;
_loadFromPrefs();
}
_initPrefs() async {
prefs ??= await SharedPreferences.getInstance();
}
_loadFromPrefs() async {
await _initPrefs();
_pageIndex = prefs!.getInt(pageIndexKey) ?? 0;
notifyListeners();
}
_savePageIndexToPrefs({required String key, required int value}) async {
await _initPrefs();
prefs!.setInt(key, value);
}
void changePageIndex(int newPageIndex) {
_pageIndex = newPageIndex;
_savePageIndexToPrefs(key: pageIndexKey, value: _pageIndex!);
notifyListeners();
}
}
CodePudding user response:
Retrieve the index of the page view in initState()
Firstly, you should change _loadFromPrefs()
method to be public
then call this method in initState()
method and assign the returning value into the PageContoller(initialPage: value)
with the following form:
in home_screen.dart
late PageController _pageController;
@override
void initState() {
super.initState();
ProviderData().loadFromPrefs().then((value) {
_pageController = PageController(initialPage: value);
});
}
in provider_data.dart
loadFromPrefs() async {
await _initPrefs();
_pageIndex = prefs!.getInt(pageIndexKey) ?? 0;
notifyListeners();
}