Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振:嵌套路由,具有持久的BottomNavigationBar,但不必构建未选择的页面_Flutter_Dart - Fatal编程技术网

Flutter 颤振:嵌套路由,具有持久的BottomNavigationBar,但不必构建未选择的页面

Flutter 颤振:嵌套路由,具有持久的BottomNavigationBar,但不必构建未选择的页面,flutter,dart,Flutter,Dart,在整个过程中,我搜索并看到了很多解决嵌套导航问题的方法,其中有一个持久的BottomNavigationBar用于Flatter应用程序。其中一些使用带有IndexedStack或PageView等的导航器。所有这些选项卡都工作得很好,除了不必要地构建未选择的选项卡(有时甚至在每次切换选项卡时都重新构建所有选项卡),从而使解决方案无法执行。我终于想出了解决这个问题的办法,因为我自己也在努力解决这个问题。这个办法非常基本,但希望你能在它的基础上进一步改进和适应它。它实现了以下目标: 嵌套导航,同

在整个过程中,我搜索并看到了很多解决嵌套导航问题的方法,其中有一个持久的BottomNavigationBar用于Flatter应用程序。其中一些使用带有IndexedStack或PageView等的导航器。所有这些选项卡都工作得很好,除了不必要地构建未选择的选项卡(有时甚至在每次切换选项卡时都重新构建所有选项卡),从而使解决方案无法执行。我终于想出了解决这个问题的办法,因为我自己也在努力解决这个问题。

这个办法非常基本,但希望你能在它的基础上进一步改进和适应它。它实现了以下目标:

  • 嵌套导航,同时保留底部导航栏
  • 不生成选项卡,除非已选择该选项卡
  • 保留导航状态
  • 保留滚动状态(例如ListView)
进口“包装:颤振/材料.省道”

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<Widget> _pages;

  List<BottomNavigationBarItem> _items = [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: "Home",
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.messenger_rounded),
      label: "Messages",
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.settings),
      label: "Settings",
    )
  ];

  int _selectedPage;

  @override
  void initState() {
    super.initState();
    _selectedPage = 0;

    _pages = [
      MyPage(
        1,
        "Page 01",
        MyKeys.getKeys().elementAt(0),
      ),
      // This avoid the other pages to be built unnecessarily
      SizedBox(),
      SizedBox(),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: WillPopScope(
        onWillPop: () async {
          return !await Navigator.maybePop(
            MyKeys.getKeys()[_selectedPage].currentState.context,
          );
        },
        child: IndexedStack(
          index: _selectedPage,
          children: _pages,
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: _items,
        currentIndex: _selectedPage,
        onTap: (index) {
          setState(() {
            // now check if the chosen page has already been built
            // if it hasn't, then it still is a SizedBox
            if (_pages[index] is SizedBox) {
              if (index == 1) {
                _pages[index] = MyPage(
                  1,
                  "Page 02",
                  MyKeys.getKeys().elementAt(index),
                );
              } else {
                _pages[index] = MyPage(
                  1,
                  "Page 03",
                  MyKeys.getKeys().elementAt(index),
                );
              }
            }

            _selectedPage = index;
          });
        },
      ),
    );
  }
}

class MyPage extends StatelessWidget {
  MyPage(this.count, this.text, this.navigatorKey);
  final count;
  final text;
  final navigatorKey;
  @override
  Widget build(BuildContext context) {
    // You'll see that it will only print once
    print("Building $text with count: $count");
    return Navigator(
      key: navigatorKey,
      onGenerateRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          builder: (BuildContext context) {
            return Scaffold(
              appBar: AppBar(
                title: Text(this.text),
              ),
              body: Center(
                child: RaisedButton(
                  child: Text(this.count.toString()),
                  onPressed: () {
                    Navigator.of(context).push(MaterialPageRoute(
                        builder: (ctx) => MyCustomPage(count + 1, text)));
                  },
                ),
              ),
            );
          },
        );
      },
    );
  }
}

class MyCustomPage extends StatelessWidget {
  MyCustomPage(this.count, this.text);
  final count;
  final text;
  @override
  Widget build(BuildContext parentContext) {
    return Scaffold(
      appBar: AppBar(
        title: Text(this.text),
      ),
      body: Column(
        children: [
          Expanded(
            child: Container(
              child: ListView.builder(
                itemCount: 15,
                itemBuilder: (context, index) {
                  return Container(
                    width: double.infinity,
                    child: Card(
                      child: Center(
                        child: RaisedButton(
                          child: Text(this.count.toString() + " pos($index)"),
                          onPressed: () {
                            Navigator.of(parentContext).push(MaterialPageRoute(
                                builder: (ctx) =>
                                    MyCustomPage(count + 1, text)));
                          },
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class MyKeys {
  static final first = GlobalKey(debugLabel: 'page1');
  static final second = GlobalKey(debugLabel: 'page2');
  static final third = GlobalKey(debugLabel: 'page3');

  static List<GlobalKey> getKeys() => [first, second, third];
}
void main(){
runApp(材料应用程序)(
主页:MyApp(),
));
}
类MyApp扩展了StatefulWidget{
@凌驾
_MyAppState createState()=>\u MyAppState();
}
类MyAppState扩展了状态{
列表页面;
列表项=[
底部导航气压计(
图标:图标(Icons.home),
标签:“主页”,
),
底部导航气压计(
图标:图标(图标。messenger_四舍五入),
标签:“信息”,
),
底部导航气压计(
图标:图标(图标.设置),
标签:“设置”,
)
];
int_选择的页面;
@凌驾
void initState(){
super.initState();
_selectedPage=0;
_页数=[
我的网页(
1.
“第01页”,
MyKeys.getKeys().elementAt(0),
),
//这样可以避免不必要地构建其他页面
SizedBox(),
SizedBox(),
];
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:Willposcope(
onWillPop:()异步{
返回!等待Navigator.maybePop(
MyKeys.getKeys()[\u selectedPage].currentState.context,
);
},
子:IndexedStack(
索引:\ u所选页面,
儿童:_页,
),
),
底部导航栏:底部导航栏(
项目:_项目,
currentIndex:_selectedPage,
onTap:(索引){
设置状态(){
//现在检查所选页面是否已经生成
//如果没有,那么它仍然是一个有大小的盒子
如果(_pages[index]是SizedBox){
如果(索引==1){
_页面[索引]=我的页面(
1.
“第02页”,
MyKeys.getKeys().elementAt(索引),
);
}否则{
_页面[索引]=我的页面(
1.
“第03页”,
MyKeys.getKeys().elementAt(索引),
);
}
}
_selectedPage=索引;
});
},
),
);
}
}
类MyPage扩展了无状态小部件{
MyPage(this.count、this.text、this.navigatorKey);
最后计数;
最后文本;
最终航行工作;
@凌驾
小部件构建(构建上下文){
//您将看到它只打印一次
打印(“生成带计数的$text:$count”);
返回导航器(
关键:导航工作,
onGenerateRoute:(路由设置){
返回物料路线(
生成器:(BuildContext上下文){
返回脚手架(
appBar:appBar(
标题:文本(this.Text),
),
正文:中(
孩子:升起按钮(
child:Text(this.count.toString()),
已按下:(){
导航器.of(上下文).push(MaterialPageRoute(
生成器:(ctx)=>MyCustomPage(计数+1,文本));
},
),
),
);
},
);
},
);
}
}
类MyCustomPage扩展了无状态小部件{
MyCustomPage(this.count、this.text);
最后计数;
最后文本;
@凌驾
小部件构建(BuildContext parentContext){
返回脚手架(
appBar:appBar(
标题:文本(this.Text),
),
正文:专栏(
儿童:[
扩大(
子:容器(
子项:ListView.builder(
物品计数:15,
itemBuilder:(上下文,索引){
返回容器(
宽度:double.infinity,
孩子:卡片(
儿童:中心(
孩子:升起按钮(
child:Text(this.count.toString()+“pos($index)”,
已按下:(){
导航器.of(parentContext).push(MaterialPage路由(
建造商:(ctx)=>
MyCustomPage(计数+1,文本));
},
),
),
),
);
},
),
),
),
],
),
);
}
}
类MyKey{
静态final first=GlobalKey(debugLabel:'page1');
静态最后一秒=GlobalKey(debugLabel:'page2');
静态最后三分之一=GlobalKey(debugLabel:'page3');
静态列表getKeys()=>[第一、第二、第三];
}

感谢您提供此解决方案。我发现的问题是,在iOS上点击状态栏时,视图没有滚动到顶部。有什么想法吗?