Проблема с навигацией (Ошибка: Ошибка диапазона (индекс): Индекс вне диапазона: индекс должен быть меньше 3: 3)

#flutter #flutter-layout #flutter-dependencies #flutter-test

Вопрос:

Я пытаюсь создать пользовательскую навигацию для своего приложения flutter, приложение и навигация работают нормально, пока не появится 3 экрана/страницы. Как только я добавляю 4-й экран, я получаю ошибку диапазона, стек ошибок выглядит следующим образом:

  ======== Exception caught by gesture ===============================================================
The following IndexError was thrown while handling a gesture:
RangeError (index): Index out of range: index should be less than 3: 3

When the exception was thrown, this was the stack: 
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 236:49  throw_
C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/js_array.dart 581:7             _get]
packages/test_proj/page_navigator.dart 17:35                                                                               <fn>
packages/flutter/src/material/bottom_navigation_bar.dart 987:25                                                            <fn>
packages/flutter/src/material/ink_well.dart 989:21                                                                         [_handleTap]
...
Handler: "onTap"
Recognizer: TapGestureRecognizer#86634
  debugOwner: GestureDetector
  state: ready
  won arena
  finalPosition: Offset(908.8, 678.4)
  finalLocalPosition: Offset(131.8, 5.4)
  button: 1
  sent tap down
====================================================================================================
 

Как только я добавляю четвертую страницу, я также перестаю получать вывод своего экрана на третьей странице. Это и есть код:

     class App extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => AppState();
}

class AppState extends State<App> {
  String _currentPage = "Page1";
  List<String> pageKeys = ["Page1", "Page2", "Page3, Page4"];
  Map<String, GlobalKey<NavigatorState>> _navigatorKeys = {
    "Page1": GlobalKey<NavigatorState>(),
    "Page2": GlobalKey<NavigatorState>(),
    "Page3": GlobalKey<NavigatorState>(),
    "Page4": GlobalKey<NavigatorState>(),
  };
  int _selectedIndex = 0;


  void _selectTab(String tabItem, int index) {
    if(tabItem == _currentPage ){
      _navigatorKeys[tabItem]!.currentState!.popUntil((route) => route.isFirst);
    } else {
      setState(() {
        _currentPage = pageKeys[index];
        _selectedIndex = index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        final isFirstRouteInCurrentTab =
        !await _navigatorKeys[_currentPage]!.currentState!.maybePop();
        if (isFirstRouteInCurrentTab) {
          if (_currentPage != "Page1") {
            _selectTab("Page1", 1);

            return false;
          }
        }
        // let system handle back button if we're on the first route
        return isFirstRouteInCurrentTab;
      },
      child: Scaffold(
        body: Stack(
            children:<Widget>[
              _buildOffstageNavigator("Page1"),
              _buildOffstageNavigator("Page2"),
              _buildOffstageNavigator("Page3"),
              _buildOffstageNavigator("Page4"),
            ]
        ),
        bottomNavigationBar: BottomNavigationBar(
          selectedItemColor: Colors.blueAccent,
          onTap: (int index) { _selectTab(pageKeys[index], index); },
          currentIndex: _selectedIndex,
          items: [
            BottomNavigationBarItem(
              icon: new Icon(Icons.looks_one),
              label: 'Page1'
            ),
            BottomNavigationBarItem(
              icon: new Icon(Icons.looks_two),
              label: 'Page2'
            ),
            BottomNavigationBarItem(
              icon: new Icon(Icons.looks_3),
              label: 'Page3'
            ),
            BottomNavigationBarItem(
              icon: new Icon(Icons.looks_4),
              label: 'Page4'
            ),
          ],
          type: BottomNavigationBarType.fixed,
        ),
      ),
      );

  }



  Widget _buildOffstageNavigator(String tabItem) {
    return Offstage(
      offstage: _currentPage != tabItem,
      child: TabNavigator(
        navigatorKey: _navigatorKeys[tabItem]!,
        tabItem: tabItem,
      ),
    );
  }
}
 

и….

 class TabNavigatorRoutes {
  static const String root = '/';
  static const String detail = '/detail';
}

class TabNavigator extends StatelessWidget {
  TabNavigator({required this.navigatorKey, required this.tabItem});
  final GlobalKey<NavigatorState> navigatorKey;
  final String tabItem;

  @override
  Widget build(BuildContext context) {

    Widget child = Text("plz work");
    if(tabItem == "Page1")
      child = Page1();
    else if(tabItem == "Page2")
      child = Page2();
    else if(tabItem == "Page3")
      child = Page3();
    else if(tabItem == "Page4")
      child = Page4();

    return Navigator(
      key: navigatorKey,
      onGenerateRoute: (routeSettings) {
        return MaterialPageRoute(
            builder: (context) => child
        );
      },
    );
  }
}
 

Что касается фактического содержимого страниц, то это всего лишь текстовый виджет. Пожалуйста, помогите мне, если это возможно. Спасибо.

Комментарии:

1. У вас может быть ошибка » _selectTab(«Страница 1″, 1);», Здесь страница 1 не должна иметь индекс 1, но индекс 0 и так далее до страницы 4 с индексом 3.

Ответ №1:

Последние два индекса, по — видимому, соединены в одну строку. Вот почему максимальный индекс равен 3 вместо ожидаемых 4, указывающих на ошибку: «Ошибка диапазона (индекс): Индекс вне диапазона: индекс должен быть меньше 3: 3».

 List<String> pageKeys = ["Page1", "Page2", "Page3, Page4"];
 

Это должно быть

 List<String> pageKeys = ['Page1', 'Page2', 'Page3', 'Page4'];