Reputation: 402
I need to refresh the drawer contents to apply, specifically, the font size changes made in the settings page. The drawer is defined in the MyHomePage class. A portion of my code is below. I need a way to call setState
when the user returns back from the settings page. To load the settings page my code uses the mechanism shown in the code below; it does not use Navigator
. When using a TextButton in the dashboard page, I can navigate to the settings page using Navigator
and pop back and get the settings applied by the comment of @johandanmo in github issue
where he states to use the code:
Navigator.push( context, MaterialPageRoute( builder: (context) => SecondPage()), ).then((value) => setState(() { // state update codes goes here }));
But, I need to show the settings page item in the Drawer so I can not use the above. How can I refresh the page or call setState
given the following implementation?
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var currentPage = DrawerSections.dashboard;
@override
Widget build(BuildContext context) {
var container;
switch (currentPage) {
case DrawerSections.dashboard:
container = const DashboardPage();
break;
case DrawerSections.settings:
container = const MySettingsPage();
break;
}
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: container,
drawer: Drawer(
child: SingleChildScrollView(
child: Container(
child: Column(
children: [
// const MyHeaderDrawer(),
myDrawerList(),
],
),
),
),
),
);
}
... ... ...
}
I have imported provider
package and written some codes that I'll post below.
The following is the body of my _MyHomePageState
class:
body: Consumer<SettingsProvider>(
builder: (context, provider, child) {
// Since isSettingsChangesAppliedTo_Screen__Menu_Page is a static,
// variable, we need not use an instance "provider" to access it, it
// can be directly accessed using the class name.
// if (provider.isSettingsChangesAppliedTo_Screen__Menu_Page)
if (SettingsProvider.isSettingsChangesAppliedTo_Screen__Menu_Page) {
setState(() {
applyNewSettings();
});
provider.resetSettingsStatusChange();
}
return container;
},
),
The contents of my provider_settings.dart page is:
import 'package:flutter/material.dart';
class SettingsProvider with ChangeNotifier {
static bool isSettingsChangesAppliedTo_Screen__Menu_Page = false;
bool checkSettingsStatusChangeAndNotify() {
if (isSettingsChangesAppliedTo_Screen__Menu_Page) {
notifyListeners();
return true;
} else {
// In case isSettingsChangesAppliedTo_Screen__Menu_Page is false, we need
// not, even call the notifyListeners() function. Calling for now, just in
// case.
notifyListeners();
return false;
}
}
void resetSettingsStatusChange() {
isSettingsChangesAppliedTo_Screen__Menu_Page = false;
}
}
I properly update the static variable isSettingsChangesAppliedTo_Screen__Menu_Page once settings get changed.
I am getting exception with this update to my actual code. I've created this minimal app source code in which there is no exception message but the app remains in splash screen for ever.
Upon using the suggested code, in answer, I returned Text from the provider's builder as:
body: Consumer<SettingsProvider>(
builder: (context, SettingsProvider provider, child) {
return Text(
"Hello, this is a test text.",
style: TextStyle(
fontSize: provider.fontSize,
),
);
},
),
This resulted in exception. A snapshot of the call stack is below:
Upvotes: 0
Views: 70
Reputation: 145
For what i know, there are (at least) two possible implementation for your use case:
Follow this tutorial to understand and learn how to use it.
(When he speaks about ChangeNotifiers, it's a component of Provider pattern).
UPDATE 1: You're not using the provider properly. You created the provider, but because you're setting the variable you want to change directly, without calling any method, you won't call notifyListener (and you don't need that variable to be static). More, you don't have to call setState anymore. You'll rely on data inside the provider, so if it changes, notifyListener tells to the view to change it accordingly.
In this code, you have to save you data in the provider. Try modifying you code like this
import 'package:flutter/material.dart';
class SettingsProvider with ChangeNotifier {
double fontSize = 16.0;
void changeFontSize(double value){
fontSize = value;
notifyListeners();
}
void resetSettingsStatusChange() {
fontSize = 16.0;
notifyListeners();
}
}
Then, you homePage will rely on the data in the provider, so for example:
body: Consumer<SettingsProvider>(
builder: (context,SettingsProvider provider, child) {
Text('Hello, this is a test text',
style: TextStyle(fontSize: provider.fontSize));
},
),
In this way, changing data in the provider will affect your view. What were you doing before was wrong. I advice you to watch videos and learn how to use it (it helped me).
Upvotes: 1