Flutter BottomNavigationBar 和高级导航

Posted

技术标签:

【中文标题】Flutter BottomNavigationBar 和高级导航【英文标题】:Flutter BottomNavigationBar and advanced navigation 【发布时间】:2018-10-08 09:35:50 【问题描述】:

我正在构建一个底部导航栏中包含 3 个项目的应用。当我更改选项卡时,正在呈现不同的小部件。到目前为止,一切都很好......

import 'package:flutter/material.dart';

class BottomTest extends StatefulWidget 
  State createState() => new _BottomTestState();


class _BottomTestState extends State<BottomTest> 
  List<Widget> _pages;
  Widget _selectedContent;
  int _bottomIndex;

  @override
  void initState() 
    _bottomIndex = 0;
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    _definePages();

    return Scaffold(
      appBar: AppBar(
        title: Text('Bottom Navigation Test'),
      ),
      body: _selectedContent ?? _pages[_bottomIndex],
      bottomNavigationBar: BottomNavigationBar(
            items: [
              BottomNavigationBarItem(
                  icon: Icon(Icons.add),
                  title: Text("Red")
              ),
              BottomNavigationBarItem(
                  icon: Icon(Icons.location_on),
                  title: Text("Blue")
              ),
              BottomNavigationBarItem(
                  icon: Icon(Icons.people),
                  title: Text("Green")
              )
            ],
            currentIndex: _bottomIndex,
            onTap: _onTabTapped,
        )
    );
  

  _definePages() 
    _pages = [
      Container(
          color: Colors.red,
          child: Stack(children: <Widget>[
            _defineFloatingActionButton(),
          ])
      ),
      Container(color: Colors.blue),
      Container(color: Colors.green),
    ];
  

  _defineFloatingActionButton() 
    return Align(
      alignment: Alignment.bottomRight,
      child: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () 
            //TODO: How to navigate to another page with still displaying the bottom navigation bar?
          
      ),
    );
  

  void _onTabTapped(int index) 
    setState(() 
      _bottomIndex = index;
      _selectedContent = _pages[index];
    );
  


//POST
class Post extends StatefulWidget 
  State createState() => new _PostState();


class _PostState extends State<Post> 
  @override
  Widget build(BuildContext context) 
    return Column(children: <Widget>[
      PostHeader(),
      Text('This is a post.') 
    ]);
  


//POSTHEADER
class PostHeader extends StatefulWidget 
  State createState() => new _PostHeaderState();


class _PostHeaderState extends State<PostHeader> 
  @override
  Widget build(BuildContext context) 
    return ListTile(
      leading: Text('Author'),
      onTap: () 
        //TODO: This should navigate to another page but still displaying the bottom navigation bar, too.
      ,
    );
  

但我想不出更高级导航的最佳做法。我目前面临两个问题。

    当在第一页上切换 FloatingActionButton 时,我想显示第四页,但 BottomNavigationBar 仍然需要可见且可操作。

    构建一个更复杂的应用程序,我正在处理一些嵌套类。所以在我的根页面上,有一个“Post”类,并且该帖子包含一个“PostHeader”类。在 PostHeader 中,有一个带有 onTap 回调的 ListTile,它应该会影响我的 _selectedContent。我如何定义这个回调?通过所有不同的类传递它似乎并不正确。

我考虑在我的 BottomTest.dart 中定义它并通过 Post 和 PostTile 传递它,但这对我来说似乎不是最佳实践,尤其是在谈到大量必需的回调时。

提前非常非常感谢您!

【问题讨论】:

这是一个您可以阅读的博客,它讨论了您的问题 1,不确定问题 2。它讨论了使用 TabNavigator medium.com/coding-with-flutter/… 构建动态路由的一些技巧 【参考方案1】:

我假设第四页将显示为其他三个页面中的任何一个,并且由于按钮位于第一页中,因此第四页将代替第一页,并且仍然指示第一个底部“红色” " 字段处于活动状态。

如果是这种情况,您应该为第一页创建一个独立的小部件,其中包含显示其他内容所需的所有逻辑。因此,您可以避免重建主布局,包括 BottomNavigationBar

您可以通过使用FirstPage 小部件来使用这些方面的东西:

import 'package:flutter/material.dart';

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 BottomTest(),
    );
  


class BottomTest extends StatefulWidget 
  State createState() => new _BottomTestState();


class _BottomTestState extends State<BottomTest> 
  List<Widget> _pages;
  Widget _selectedContent;
  int _bottomIndex;

  @override
  void initState() 
    _bottomIndex = 0;
    super.initState();
  

  @override
  Widget build(BuildContext context) 
    _definePages();

    return Scaffold(
        appBar: AppBar(
          title: Text('Bottom Navigation Test'),
        ),
        body: _selectedContent ?? _pages[_bottomIndex],
        bottomNavigationBar: BottomNavigationBar(
          items: [
            BottomNavigationBarItem(icon: Icon(Icons.add), title: Text("Red")),
            BottomNavigationBarItem(
                icon: Icon(Icons.location_on), title: Text("Blue")),
            BottomNavigationBarItem(
                icon: Icon(Icons.people), title: Text("Green"))
          ],
          currentIndex: _bottomIndex,
          onTap: _onTabTapped,
        ));
  

  _definePages() 
    _pages = [
      FirstPage(),
      Container(color: Colors.blue),
      Container(color: Colors.green),
    ];
  

  void _onTabTapped(int index) 
    setState(() 
      _bottomIndex = index;
      _selectedContent = _pages[index];
    );
  


//POST
class Post extends StatefulWidget 
  State createState() => new _PostState();


class _PostState extends State<Post> 
  @override
  Widget build(BuildContext context) 
    return Column(children: <Widget>[PostHeader(), Text('This is a post.')]);
  


//POSTHEADER
class PostHeader extends StatefulWidget 
  State createState() => new _PostHeaderState();


class _PostHeaderState extends State<PostHeader> 
  @override
  Widget build(BuildContext context) 
    return ListTile(
      leading: Text('Author'),
      onTap: () 
        //TODO: This should navigate to another page but still displaying the bottom navigation bar, too.
      ,
    );
  


class FirstPage extends StatefulWidget 
  @override
  _FirstPageState createState() => _FirstPageState();


class _FirstPageState extends State<FirstPage> 

  bool showFirst = true;

  _defineFloatingActionButton() 
    return Align(
      alignment: Alignment.bottomRight,
      child: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: _onButtonPressed,
      ),
    );
  

  _onButtonPressed() 
    setState(() 
      showFirst = !showFirst;
    );
  

  _buildFirst() 
    return Container(
        color: Colors.red,
        child: Stack(children: <Widget>[
          _defineFloatingActionButton(),
        ]));
  

  _buildFourth() 
    return Container(
        color: Colors.grey,
        child: Stack(children: <Widget>[
          _defineFloatingActionButton(),
        ]));
  

  @override
  Widget build(BuildContext context) 
    return showFirst ? _buildFirst() : _buildFourth();
  

对于第二点,也许您应该打开另一个问题,以便在不同的答案中保留两个或多或少不相关的问题。

【讨论】:

以上是关于Flutter BottomNavigationBar 和高级导航的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 致命错误:找不到“Flutter/Flutter.h”文件

[Flutter] flutter项目一直卡在 Running Gradle task 'assembleDebug'...

flutter 日志输出,Flutter打印日志,flutter log,flutter 真机日志

Flutter开发 Flutter 包和插件 ( Flutter 包和插件简介 | 创建 Flutter 插件 | 创建 Dart 包 )

flutter与原生混编(iOS)

Flutter-布局