Ich habe eine StatefulWidget
in Flutter with button, die mich mit Navigator.Push()
zu einer anderen StatefulWidget
navigiert. Beim zweiten Widget ändere ich den globalen Status (einige Benutzereinstellungen). Wenn ich vom zweiten Widget zum ersten zurückkomme, ist das erste Widget mit Navigator.pop()
im alten Zustand, aber ich möchte, dass es neu geladen wird. Irgendeine Idee, wie das geht? Ich habe eine Idee, aber sie sieht hässlich aus:
Es gibt ein paar Dinge, die Sie hier tun können. @ Mahis Antwort könnte korrekt sein, wenn sie etwas genauer ist und tatsächlich Push anstelle von showDialog verwendet, da das OP danach gefragt hat. Dies ist ein Beispiel, das Navigator.Push
verwendet:
import 'package:flutter/material.Dart';
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.green,
child: new Column(
children: <Widget>[
new RaisedButton(
onPressed: () => Navigator.pop(context),
child: new Text("back"),
),
],
),
);
}
}
class FirstPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => new FirstPageState();
}
class FirstPageState extends State<FirstPage> {
Color color = Colors.white;
@override
Widget build(BuildContext context) {
return new Container(
color: color,
child: new Column(
children: <Widget>[
new RaisedButton(
child: new Text("next"),
onPressed: () {
Navigator
.Push(
context,
new MaterialPageRoute(builder: (context) => new SecondPage()),
)
.then((value) {
setState(() {
color = color == Colors.white ? Colors.grey : Colors.white;
});
});
}),
],
),
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(child: child),
home: new FirstPage(),
),
);
Es gibt jedoch eine andere Möglichkeit, dies in Ihren Anwendungsfall zu integrieren. Wenn Sie global
als etwas verwenden, das sich auf den Aufbau Ihrer ersten Seite auswirkt, können Sie ein InheritedWidget verwenden, um Ihre globalen Benutzereinstellungen zu definieren. Bei jeder Änderung wird FirstPage neu erstellt. Dies funktioniert sogar in einem Stateless-Widget (siehe unten) (sollte jedoch auch in einem Stateful-Widget funktionieren).
Ein Beispiel für das Flattern von "Geerbt" ist das Theme der App, obwohl es in einem Widget definiert wird, anstatt es direkt so zu erstellen, wie ich es hier habe.
import 'package:flutter/material.Dart';
import 'package:meta/meta.Dart';
class SecondPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Container(
color: Colors.green,
child: new Column(
children: <Widget>[
new RaisedButton(
onPressed: () {
ColorDefinition.of(context).toggleColor();
Navigator.pop(context);
},
child: new Text("back"),
),
],
),
);
}
}
class ColorDefinition extends InheritedWidget {
ColorDefinition({
Key key,
@required Widget child,
}): super(key: key, child: child);
Color color = Colors.white;
static ColorDefinition of(BuildContext context) {
return context.inheritFromWidgetOfExactType(ColorDefinition);
}
void toggleColor() {
color = color == Colors.white ? Colors.grey : Colors.white;
print("color set to $color");
}
@override
bool updateShouldNotify(ColorDefinition oldWidget) =>
color != oldWidget.color;
}
class FirstPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
var color = ColorDefinition.of(context).color;
return new Container(
color: color,
child: new Column(
children: <Widget>[
new RaisedButton(
child: new Text("next"),
onPressed: () {
Navigator.Push(
context,
new MaterialPageRoute(builder: (context) => new SecondPage()),
);
}),
],
),
);
}
}
void main() => runApp(
new MaterialApp(
builder: (context, child) => new SafeArea(
child: new ColorDefinition(child: child),
),
home: new FirstPage(),
),
);
Wenn Sie ein geerbtes Widget verwenden, müssen Sie sich keine Sorgen machen, dass Sie nach dem Popup der von Ihnen geposteten Seite suchen müssen. Dies funktioniert für grundlegende Anwendungsfälle, kann jedoch in einem komplexeren Szenario zu Problemen führen.
Es gibt zwei Dinge, von denen Daten übertragen werden
Verwenden Sie dies auf der ersten Seite
// sending "Foo" from 1st
Navigator.Push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
Verwenden Sie dies auf der 2. Seite.
class Page2 extends StatelessWidget {
final String string;
Page2(this.string); // receiving "Foo" in 2nd
...
}
Verwenden Sie dies auf der 2. Seite
// sending "Bar" from 2nd
Navigator.pop(context, "Bar");
Verwenden Sie dies auf der ersten Seite, es ist dasselbe, das zuvor verwendet wurde, jedoch mit geringen Änderungen.
// receiving "Bar" in 1st
String received = await Navigator.Push(context, MaterialPageRoute(builder: (_) => Page2("Foo")));
Sie können einen dynamic result
zurückgeben, wenn Sie den Kontext öffnen, und dann setState((){})
aufrufen, wenn der Wert true
ist.
Ich habe einige Codeausschnitte als Referenz eingefügt.
handleClear() async {
try {
var delete = await deleteLoanWarning(
context,
'Clear Notifications?',
'Are you sure you want to clear notifications. This action cannot be undone',
);
if (delete.toString() == 'true') {
//call setState here to rebuild your state.
}
} catch (error) {
print('error clearing notifications' + error.toString());
}
}
Future<bool> deleteLoanWarning(BuildContext context, String title, String msg) async {
return await showDialog<bool>(
context: context,
child: new AlertDialog(
title: new Text(
title,
style: new TextStyle(fontWeight: fontWeight, color: CustomColors.continueButton),
textAlign: TextAlign.center,
),
content: new Text(
msg,
textAlign: TextAlign.justify,
),
actions: <Widget>[
new Container(
decoration: boxDecoration(),
child: new MaterialButton(
child: new Text('NO',),
onPressed: () {
Navigator.of(context).pop(false);
},
),
),
new Container(
decoration: boxDecoration(),
child: new MaterialButton(
child: new Text('YES', ),
onPressed: () {
Navigator.of(context).pop(true);
},
),
),
],
),
) ??
false;
}
Viele Grüße Mahi
Sie können pushReplacement verwenden und die neue Route angeben
Heute habe ich mich mit der gleichen Situation konfrontiert, aber ich habe es auf viel einfachere Weise gelöst. Ich habe gerade eine globale Variable definiert, die in der ersten stateful-Klasse verwendet wurde. Wenn ich zu einem zweiten stateful-Widget navigiere, lasse ich es den Wert des globalen aktualisieren Variable, die das erste Widget automatisch zur Aktualisierung zwingt. Hier ist ein Beispiel (ich habe es eilig geschrieben, also habe ich kein Gerüst oder eine Material-App installiert, ich wollte nur meinen Standpunkt veranschaulichen):
import 'package:flutter/material.Dart';
int count = 0 ;
class FirstPage extends StatefulWidget {
FirstPage({Key key}) : super(key: key);
@override
_FirstPageState createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
@override
Widget build(BuildContext context) {
return InkWell(
onTap(){
Navigator.of(context).Push(MaterialPageRoute(builder: (context) =>
new SecondPage());
},
child: Text('First', style : TextStyle(fontSize: count == 0 ? 20.0 : 12.0)),
),
}
class SecondPage extends StatefulWidget {
SecondPage({Key key}) : super(key: key);
@override
_SecondPageState createState() => _SecondPageState();
}
class _SecondPageState extends State<SecondPage> {
@override
Widget build(BuildContext context) {
return IconButton(
icon: new Icon(Icons.add),
color: Colors.amber,
iconSize: 15.0,
onPressed: (){
count++ ;
},
),
}
// setze dies dort, wo du auf den zweiten Bildschirm drückst (innerhalb einer asynchronen Funktion)
Function f;
f = await Navigator.pushNamed(context, 'Screenname');
f();
// Setze dies dort, wo du auftauchst
Navigator.pop(context, () {setState(() {});}
// Dies bewirkt, dass die Funktion setState nach dem Aufspringen als Argument an den Bildschirm übergeben wird