У меня есть интерфейс с двумя кнопками, которые выдвигаются и возвращают истину или ложь, вот так:
onPressed: () => Navigator.pop(context, false)
Мне нужно адаптировать кнопку "Назад" в панели приложений, чтобы она появлялась, а также возвращала ложь. Есть ли способ сделать это?
9 ответов
Это может помочь и работать для вас
1-й экран
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-й экран
Navigator.pop(context, "Hello world");
Чтобы получить данные и передать их обратно в навигацию, необходимо использовать .then()
на экране 1. Ниже приведен пример.
Экран 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
),
Экран 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
});
}
}
По умолчанию BackButton
принимает ведущее свойство вашего AppBar
, поэтому все, что вам нужно сделать, это переопределить свойство leading
с помощью пользовательской кнопки возврата, например:
leading: IconButton(icon:Icon(Icons.chevron_left),onPressed:() => Navigator.pop(context, false),),)
Более простой способ - обернуть тело в WillPopScope , таким образом, оно будет работать с кнопкой «Назад» сверху и кнопкой «Android назад» снизу .
Вот пример, где обе кнопки возврата возвращают false:
final return = Navigator.of(context).push(MaterialPageRoute<bool>(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("New Page"),
),
body: WillPopScope(
onWillPop: () {
Navigator.pop(context, false);
return new Future(() => false);
},
child: newPageStuff(),
),
);
},
));
В других ответах они предложили использовать:
ведущий: BackButton (...)
Я обнаружил, что это работает с кнопкой «Назад» сверху, а не с Android.
Я все равно включаю пример:
final return = Navigator.of(context).push(MaterialPageRoute<bool>(
builder: (BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: BackButton(
onPressed: () => Navigator.pop(context, false),
),
title: Text("New Page"),
),
body: newPageStuff(),
);
},
));
Хотя вы можете переопределить кнопку «Назад» для пользовательских действий, не делайте этого.
Вместо того, чтобы переопределять кнопку с помощью пользовательского всплывающего окна, вы должны обработать нулевой сценарий. Есть несколько причин, по которым вы не хотите переопределять значок вручную:
- Значок меняется на IOS и Android. В IOS он использует
arrow_back_ios
, в то время как Android используетarrow_back
- Значок может автоматически исчезнуть, если нет пути назад
- Физическая кнопка возврата все равно вернет
null
.
Вместо этого следует сделать следующее:
var result = await Navigator.pushNamed<bool>(context, "/");
if (result == null) {
result = false;
}
Самый простой способ добиться этого - это:
В своем теле возьмите WillPopScope
в качестве родительского виджета И по его onWillPop : () {}
вызову
Navigator.pop(context, false);
onWillPop
из WillPopScope
будет запущен автоматически, когда вы нажмете кнопку возврата на панели приложений
Сначала удалите автоматически добавленную кнопку «Назад» (см. этот ответ).
Затем создайте свою собственную кнопку возврата. нравится:
IconButton(
onPressed: () => Navigator.pop(context, false),
icon: Icon(Icons.arrow_back),
)
Используйте приведенный ниже код, чтобы получить результат от вашей деятельности.
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';
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,),
);
}
}
Получить полный пример того, как работать с этим здесь
Вы можете передавать данные / аргументы с одного экрана на другой,
Рассмотрим этот пример:
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),
));
}),
),
);
}
}
Экран 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),
));
}),
),
);
}
}
Чтобы передавать данные между экранами, передайте аргумент / данные конструктору Screens в Navigator.pushReplacement()
. Вы можете передать столько аргументов, сколько захотите.
Эта линия
Navigator.pushReplacement(context, new MaterialPageRoute(
builder: (BuildContext context) => new Screen1(indx),
));
Перейдем к Screen1 и вызовем initState и создадим метод Screen1, чтобы вы могли получить обновленные значения.
Связанные вопросы
Новые вопросы
flutter
Flutter - это набор средств разработки пользовательского интерфейса с открытым исходным кодом, созданный Google. Он используется для разработки приложений для Android, iOS, Linux, Mac, Windows, Google Fuchsia и Интернета из единой кодовой базы. Приложения Flutter написаны на языке Dart.