Reputation: 20231
Let's say I have a few sliders and switches on my page, I change their state and modify them, I understand that we do setState
to show the changed state of the widget tree and rebuild it, but I would like to know if there's a way to undo all those changes and go back to the initial state (state the app was when it was first built)?
I don't want to call a custom function which manually resets the variables to initial values. Nor the routes should be removed and added back (because it would show the transition)
Upvotes: 10
Views: 35293
Reputation: 267554
If you want to do things out of the box
Use any of the below:
Navigator.pushReplacementNamed(context, '/currentRoute');
Navigator.popAndPushNamed(context, '/currentRoute');
void main() => runApp(MaterialApp(home: DummyWidget()));
class DummyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) => HomePage();
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _enabled = false; // For Switch
double _value = 0; // For Slider
// This is the trick!
void _reset() {
Navigator.pushReplacement(
context,
PageRouteBuilder(
transitionDuration: Duration.zero,
pageBuilder: (_, __, ___) => DummyWidget(),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Switch(
value: _enabled,
onChanged: (newValue) => setState(() => _enabled = newValue),
),
Slider(
value: _value,
onChanged: (newValue) => setState(() => _value = newValue),
),
TextButton(
onPressed: _reset,
child: Text('RESET'),
),
],
),
);
}
}
A better approach might be with keys. Here's the key approach
Upvotes: 21
Reputation: 267554
Screenshot:
Using key
to change the state.
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _count = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
body: KeyedSubtree(
key: ValueKey<int>(_count),
child: Column(
children: [
MainPage(),
ElevatedButton(
onPressed: () => setState(() => ++_count),
child: Text('RESET'),
)
],
),
),
);
}
}
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
bool _enabled = false; // For Switch
double _value = 0; // For Slider.
@override
Widget build(BuildContext context) {
return Column(
children: [
Switch(
value: _enabled,
onChanged: (newValue) => setState(() => _enabled = newValue),
),
Slider(
value: _value,
onChanged: (newValue) => setState(() => _value = newValue),
),
],
);
}
}
Upvotes: 6
Reputation: 754
A simple trick would be to pop and push with the same route. Like this:
Navigator.popAndPushNamed(context, "same_route");
Upvotes: 9
Reputation: 1859
There are a couple of age-old design patterns that might be useful in this situation. Having a reset option is cool, but what's cooler is undo.
See how the Command and Memento patterns can be implemented in Flutter with these tutorials: Command | Memento
Upvotes: 2
Reputation: 267554
Screenshot:
Full Code:
void main() {
runApp(
MaterialApp(
// Passing initial values
home: HomePage(enabled: false, value: 0),
),
);
}
class HomePage extends StatefulWidget {
final bool enabled;
final double value;
HomePage({this.enabled = false, this.value = 0});
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _initialEnabled, _enabled; // For Switches
double _initialValue, _value; // For Sliders
@override
void initState() {
super.initState();
// Assign them once (initial data)
_initialEnabled ??= widget.enabled;
_initialValue ??= widget.value;
// These values can be changed by respective widgets
_enabled = _initialEnabled;
_value = _initialValue;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Switch(
value: _enabled,
onChanged: (value) => setState(() => _enabled = value),
),
Slider(
value: _value,
onChanged: (value) => setState(() => _value = value),
),
RaisedButton(
onPressed: () {
setState(() {
// Resetting the values to initial ones which were passed
_enabled = _initialEnabled;
_value = _initialValue;
});
},
child: Text('RESET'),
),
],
),
),
);
}
}
Upvotes: 1
Reputation: 587
You can call YourStateClass.initState()
to revert to its original initialized state.
Also make sure that when you construct your state, you will want to initialize all of your variables in the void initState()
function.
ex.
class FooState extends State<Foo> {
int someVariable;
@override
void initState() {
someVariable = 0;
}
}
You need to have all of your variables assigned a value in the initState()
function in order for this to work.
For more info check out the docs at: https://api.flutter.dev/flutter/widgets/State/initState.html
Upvotes: 0
Reputation: 619
Here is one way of many to reset to the initial data
import 'package:flutter/material.dart';
List<String> initialData = ['First', 'Second', 'Third'];
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Example(),
);
}
}
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
List<String> items = [];
@override
void initState() {
fillInitialData();
super.initState();
}
fillInitialData() {
items.addAll(initialData);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Example')),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return Card(
child: Padding(
padding: EdgeInsets.all(16.0),
child: Text(items[index]),
),
);
},
),
),
Row(
children: <Widget>[
FlatButton(
onPressed: () {
setState(() {
items.add('A new item');
});
},
child: Text('Add an item'),
),
FlatButton(
onPressed: () {
setState(() {
items.clear();
fillInitialData();
});
},
child: Text('Reset'),
),
],
),
],
),
);
}
}
Upvotes: 1