У меня есть интерфейс с двумя кнопками, которые выдвигаются и возвращают истину или ложь, вот так:

onPressed: () => Navigator.pop(context, false)

Мне нужно адаптировать кнопку "Назад" в панели приложений, чтобы она появлялась, а также возвращала ложь. Есть ли способ сделать это?

19
aksn 20 Авг 2018 в 12:34

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");
15
Dhruvan Bhalara 18 Фев 2020 в 06:08

Чтобы получить данные и передать их обратно в навигацию, необходимо использовать .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
        });
      }
   }
7
Deepak Thakur 31 Янв 2019 в 07:49

По умолчанию BackButton принимает ведущее свойство вашего AppBar, поэтому все, что вам нужно сделать, это переопределить свойство leading с помощью пользовательской кнопки возврата, например:

leading: IconButton(icon:Icon(Icons.chevron_left),onPressed:() => Navigator.pop(context, false),),)
21
aziza 20 Авг 2018 в 10:19

Более простой способ - обернуть тело в 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(),
      );
    },
));
7
Apoleo 26 Фев 2020 в 19:42

Хотя вы можете переопределить кнопку «Назад» для пользовательских действий, не делайте этого.

Вместо того, чтобы переопределять кнопку с помощью пользовательского всплывающего окна, вы должны обработать нулевой сценарий. Есть несколько причин, по которым вы не хотите переопределять значок вручную:

  • Значок меняется на IOS и Android. В IOS он использует arrow_back_ios, в то время как Android использует arrow_back
  • Значок может автоматически исчезнуть, если нет пути назад
  • Физическая кнопка возврата все равно вернет null.

Вместо этого следует сделать следующее:

var result = await Navigator.pushNamed<bool>(context, "/");
if (result == null) {
  result = false;
}
5
Rémi Rousselet 20 Авг 2018 в 12:25

Самый простой способ добиться этого - это:

В своем теле возьмите WillPopScope в качестве родительского виджета И по его onWillPop : () {} вызову

Navigator.pop(context, false);

onWillPop из WillPopScope будет запущен автоматически, когда вы нажмете кнопку возврата на панели приложений

3
Mohammad Ersan 26 Апр 2020 в 22:56

Сначала удалите автоматически добавленную кнопку «Назад» (см. этот ответ).

Затем создайте свою собственную кнопку возврата. нравится:

IconButton(
    onPressed: () => Navigator.pop(context, false),
    icon: Icon(Icons.arrow_back),
    )
0
Yamin 20 Авг 2018 в 09:45

Используйте приведенный ниже код, чтобы получить результат от вашей деятельности.

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,),
  );
 }
}

Получить полный пример того, как работать с этим здесь

0
Zulfiqar 20 Авг 2018 в 09:53

Вы можете передавать данные / аргументы с одного экрана на другой,

Рассмотрим этот пример:

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, чтобы вы могли получить обновленные значения.

0
ArgaPK 8 Ноя 2018 в 10:19
51927885