Flutter BottomNavigationBar和高级导航

时间:2018-10-08 09:35:50

标签: flutter flutter-layout

我正在底部的导航栏中构建一个包含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.
      },
    );
  }
}

但是我无法找出最佳实践来进行更高级的导航。我目前面临2个问题。

  1. 当在第一页上单击FloatingActionButton时,我想显示第四页,但BottomNavigationBar仍需要可见且可操作。

  2. 构建一个更复杂的应用程序,我正在处理少数嵌套类。因此,在我的根页面上,有一个类“ Post”,该帖子包含一个类“ PostHeader”。在PostHeader中,有一个带有onTap回调的ListTile,它将影响我的_selectedContent。如何定义此回调?通过所有不同的类似乎都不正确。

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

非常非常感谢您!

1 个答案:

答案 0 :(得分:0)

我假设第四页将显示为其他三个页面中的任何一个,并且由于该按钮位于第一页中,因此第四页将代替第一页,并且仍会向第一个底部显示“红色” “字段为有效。

如果是这种情况,则应为第一页创建一个独立的小部件,其中应包含显示其他内容所需的所有逻辑。这样就避免了重建主布局,包括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();
  }
}

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