J'ai une interface avec deux boutons qui apparaissent et retournent vrai ou faux, comme ceci:
onPressed: () => Navigator.pop(context, false)
J'ai besoin d'adapter le bouton de retour dans la barre d'applications, donc il apparaît et renvoie également faux. Existe-t-il un moyen d'y parvenir?
Cela peut vous aider et fonctionner pour vous
1er écran
void goToSecondScreen()async {
var result = await Navigator.Push(_context, new MaterialPageRoute(
builder: (BuildContext context) => new SecondScreen(context),
fullscreenDialog: true,)
);
Scaffold.of(_context).showSnackBar(SnackBar(content: Text("$result"),duration: Duration(seconds: 3),));
}
2ème écran
Navigator.pop(context, "Hello world");
La valeur par défaut BackButton
reprend la propriété principale de votre AppBar
, il vous suffit donc de remplacer la propriété leading
par votre bouton de retour personnalisé, par exemple:
leading: IconButton(icon:Icon(Icons.chevron_left),onPressed:() => Navigator.pop(context, false),),)
Pour faire apparaître les données et retransmettre les données de navigation, vous devez utiliser .then()
à partir de l'écran 1. Voici l'exemple.
Écran 2:
class DetailsClassWhichYouWantToPop {
final String date;
final String amount;
DetailsClassWhichYouWantToPop(this.date, this.amount);
}
void getDataAndPop() {
DetailsClassWhichYouWantToPop detailsClass = new DetailsClassWhichYouWantToPop(dateController.text, amountController.text);
Navigator.pop(context, detailsClass); //pop happens here
}
new RaisedButton(
child: new Text("Edit"),
color: UIData.col_button_orange,
textColor: Colors.white,
onPressed: getDataAndPop, //calling pop here
),
Écran 1:
class Screen1 extends StatefulWidget {
//var objectFromEditBill;
DetailsClassWhichYouWantToPop detailsClass;
MyBills({Key key, this.detailsClass}) : super(key: key);
@override
Screen1State createState() => new Screen1State();
}
class Screen1State extends State<Screen1> with TickerProviderStateMixin {
void getDataFromEdit(DetailsClassWhichYouWantToPop detailClass) {
print("natureOfExpense Value:::::: " + detailClass.date);
print("receiptNumber value::::::: " + detailClass.amount);
}
void getDataFromEdit(DetailsClassWhichYouWantToPop detailClass) {
print("natureOfExpense Value:::::: " + detailClass.natureOfExpense);
print("receiptNumber value::::::: " + detailClass.receiptNumber);
}
void pushFilePath(File file) async {
await Navigator.Push(
context,
MaterialPageRoute(
builder: (context) => Screen2(fileObj: file),
),
).then((val){
getDataFromScreen2(val); //you get details from screen2 here
});
}
}
Bien que vous puissiez remplacer le bouton de retour pour les comportements personnalisés, ne le faites pas.
Au lieu de remplacer le bouton par un pop personnalisé, vous devez gérer le scénario nul. Il y a plusieurs raisons pour lesquelles vous ne voulez pas remplacer manuellement l'icône:
arrow_back_ios
while Android utilise arrow_back
null
.Au lieu de cela, procédez comme suit:
var result = await Navigator.pushNamed<bool>(context, "/");
if (result == null) {
result = false;
}
La façon la plus simple d'y parvenir est de:
Dans votre corps, prenez un WillPopScope comme widget parent Et sur son onPop: () {} appel
Navigator.pop(context, false);
onPop de WillPopScope sera déclenché automatiquement lorsque vous appuierez sur le bouton de retour de votre barre d'applications
Vous pouvez passer des données/arguments d'un écran à l'autre,
considérez cet exemple:
screen1.Dart:
import 'package:flutter/material.Dart';
import 'screen2.Dart';
class Screen1 extends StatelessWidget {
Screen1(this.indx);
final int indx;
@override
Widget build(BuildContext context) {
return new S1(indx: indx,);
}
}
class S1 extends StatefulWidget {
S1({Key key, this.indx}) : super(key: key);
final int indx;
@override
S1State createState() => new S1State(indx);
}
class S1State extends State<VD> {
int indx = 5;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new IconButton(icon: const Icon(Icons.iconName), onPressed: () {
Navigator.pushReplacement(context, new MaterialPageRoute(
builder: (BuildContext context) => new Screen2(indx),
));
}),
),
);
}
}
Écran 2:
import 'package:flutter/material.Dart';
import 'screen2.Dart';
class Screen2 extends StatelessWidget {
Screen2(this.indx);
final int indx;
@override
Widget build(BuildContext context) {
return new S2(indx: indx,);
}
}
class S2 extends StatefulWidget {
S2({Key key, this.indx}) : super(key: key);
final int indx;
@override
S2State createState() => new S2State(indx);
}
class S2State extends State<VD> {
int indx = 1;
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
leading: new IconButton(icon: const Icon(Icons.Icons.arrow_back), onPressed: () {
Navigator.pushReplacement(context, new MaterialPageRoute(
builder: (BuildContext context) => new Screen1(indx),
));
}),
),
);
}
}
Pour passer des données entre les écrans, passez l'argument/les données au constructeur Screens dans Navigator.pushReplacement()
. Vous pouvez passer autant d'arguments que vous le souhaitez.
Cette ligne
Navigator.pushReplacement(context, new MaterialPageRoute(
builder: (BuildContext context) => new Screen1(indx),
));
ira à Screen1 et appellera initState et construira la méthode de Screen1 afin que vous puissiez obtenir des valeurs mises à jour.
Utilisez le code ci-dessous pour obtenir le résultat de votre activité.
Future _startActivity() async {
Map results = await Navigator.of(context).Push(new MaterialPageRoute(builder: (BuildContext context){
return new StartActivityForResult();
}));
if (results != null && results.containsKey('item')) {
setState(() {
stringFromActivity = results['item'];
print(stringFromActivity);
});
}
}
Code source complet
import 'package:flutter/material.Dart';
import 'activity_for_result.Dart';
import 'Dart:async';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Start Activity For Result'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String stringFromActivity = 'Start Activity To Change Me \n????????????';
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
stringFromActivity, style: new TextStyle(fontSize: 20.0), textAlign: TextAlign.center,
),
new Container(height: 20.0,),
new RaisedButton(child: new Text('Start Activity'),
onPressed: () => _startActivity(),)
],
),
),
);
}
Future _startActivity() async {
Map results = await Navigator.of(context).Push(new MaterialPageRoute(builder: (BuildContext context){
return new StartActivityForResult();
}));
if (results != null && results.containsKey('item')) {
setState(() {
stringFromActivity = results['item'];
print(stringFromActivity);
});
}
}
}
import 'package:flutter/material.Dart';
class StartActivityForResult extends StatelessWidget{
List<String>list = ['????????????','????????????','????????????','????????????','????????????','????????????','????','????','????',];
@override
Widget build(BuildContext context) {
// TODO: implement build
return new Scaffold(
appBar: new AppBar(
title: new Text('Selecte Smily'),
),
body: new ListView.builder(itemBuilder: (context, i){
return new ListTile(title: new Text(list[i]),
onTap: (){
Navigator.of(context).pop({'item': list[i]});
},
);
}, itemCount: list.length,),
);
}
}
obtenir un exemple complet de fonctionnement de cela à partir de ici
Tout d'abord, supprimez le bouton de retour automatiquement ajouté (voir cette réponse )
Ensuite, créez votre propre bouton de retour. comme ça:
IconButton(
onPressed: () => Navigator.pop(context, false),
icon: Icon(Icons.arrow_back),
)