Как получить текущий маршрут маршрута в Flutter?

При реализации постоянной нижней панели предыдущий маршрут необходимо восстановить при нажатии кнопки на нижней панели.

При нажатии кнопки на нижней панели ее текущий путь маршрута (/a/b/c) сохраняется, а ранее сохраненный маршрут восстанавливается в соответствии с нажатием кнопки.

Концептуально пользователь будет считать каждую кнопку рабочим пространством, и ее состояние никогда не будет потеряно (включая задний стек). Пользователь может безопасно переключаться с одного рабочего места на другое.

Как получить текущий маршрут маршрута во Flutter, когда маршрутизация перематывается на root?

Ответ 1

NavigatorState не предоставляет API для получения пути к текущему маршруту, а Route также не предоставляет API для определения пути к маршруту. Маршруты могут быть (и часто являются) анонимными. Вы можете выяснить, находится ли данный Route на вершине стека навигатора прямо сейчас, используя метод isCurrent, но это не очень удобно для вашего случая использования.

Я бы порекомендовал вам по-другому взглянуть на эту проблему и вообще не перематывать рут. Вместо этого используйте разные виджеты Navigator для каждой панели BottomNavigationBar. Таким образом, вам не придется перематывать стек при переключении между панелями. Вы можете обернуть свои виджеты Navigator в виджеты Opacity и IgnorePointer, чтобы скрыть их, когда они не должны быть видны, не разрушая их стек.

app video

import 'package:flutter/material.dart';

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      home: new MyHomePage(),
    );
  }
}

class SecurePage extends StatelessWidget {
  final int index;

  SecurePage(this.index);

  Widget build(BuildContext context) {
    return new Material(
      color: Colors.amber,
      child: new InkWell(
        child: new Center(
          child: new Icon(
            Icons.security,
            color: Colors.white,
            size: index * 100.0 + 20.0,
          ),
        ),
        onTap: () {
          Navigator.of(context).push(
            new MaterialPageRoute(
              builder: (BuildContext context) {
                return new SecurePage(index + 1);
              },
            ),
          );
        },
      ),
    );
  }
}

class VerifiedPage extends StatelessWidget {
  final int index;

  VerifiedPage(this.index);

  Widget build(BuildContext context) {
    return new Material(
      color: Colors.green,
      child: new InkWell(
        child: new Center(
          child: new Icon(
            Icons.verified_user,
            color: Colors.white,
            size: index * 100.0 + 20.0,
          ),
        ),
        onTap: () {
          Navigator.of(context).push(
            new MaterialPageRoute(
              builder: (BuildContext context) {
                return new VerifiedPage(index + 1);
              },
            ),
          );
        },
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State createState() => new MyHomePageState();
}

class MyHomePageState extends State<MyHomePage> {
  int _page = 0;
  List<Widget> initialWidgets = <Widget>[
    new SecurePage(0),
    new VerifiedPage(0),
  ];

  Widget build(BuildContext context) {
    return new Scaffold(
      body: new Stack(
        children: new List<Widget>.generate(initialWidgets.length, (int index) {
          return new IgnorePointer(
            ignoring: index != _page,
            child: new Opacity(
              opacity: _page == index ? 1.0 : 0.0,
              child: new Navigator(
                onGenerateRoute: (RouteSettings settings) {
                  return new MaterialPageRoute(
                    builder: (_) => initialWidgets[index],
                  );
                },
              ),
            ),
          );
        }),
      ),
      bottomNavigationBar: new BottomNavigationBar(
        currentIndex: _page,
        onTap: (int index) {
          setState(() {
            _page = index;
          });
        },
        items: <BottomNavigationBarItem>[
          new BottomNavigationBarItem(
            icon: new Icon(Icons.security),
            title: new Text('Secure'),
          ),
          new BottomNavigationBarItem(
            icon: new Icon(Icons.verified_user),
            title: new Text('Verified'),
          ),
        ],
      ),
    );
  }
}

Ответ 2

Это должно дать вам точное название маршрута

import 'package:path/path.dart';

ModalRoute.of(context).settings.name

Ответ 3

Публикация этого ответа в основном для архивных целей, но, как упоминал @ikben, один из способов получить текущий маршрут и все его свойства - это ModalRoute.of(context). Это возвращает ModalRoute, что, несмотря на его название, применимо к большинству вызовов Navigator.push, а не только к showDialog. Полезные свойства: Route.settings, Route.navigator и Route.isFirst.

Ответ 4

Колин - у предлагаемого вами подхода возникают проблемы, когда на вкладках содержатся элементы textField. Они не кликабельны. Только самая последняя страница (которая в вашем примере является проверенной вкладкой, позволит текстовым полям иметь фокус и быть доступным).

Проблема, которую я считаю, - это контекст, из которого вызывается навигатор. Даже если у вас есть IgnorePointer, который оборачивает Opacity - любые TextFields не получат фокуса в вашем решении, это ограничение вложенной навигации?