草庐IT

Flutter BottomNavigationBar 和高级导航

coder 2023-07-23 原文

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

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

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

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

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

非常非常感谢您!

最佳答案

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

如果是这种情况,您应该为第一页创建一个独立的小部件,其中包含显示其他内容所需的所有逻辑。因此,您可以避免重建主要布局,包括 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 和高级导航,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52699361/

有关Flutter BottomNavigationBar 和高级导航的更多相关文章

  1. ruby - 高级语言是否使用数据结构? - 2

    我目前还在上学,正在上一门关于用C++实现数据结构的类(class)。在业余时间,我喜欢使用“高级”语言(主要是Ruby和一些c#)进行编程。既然这些高级语言为你管理内存,你会用数据结构做什么?我可以理解对队列和堆栈的需求,但是您需要在Ruby中使用二叉树吗?还是2-3-4树?为什么?谢谢。 最佳答案 Sosincethesehigherlevellanguagesmanagethememoryforyou,whatwouldyouusedatastructuresfor?使用数据结构的主要原因与垃圾收集无关。但它是以某种方式有效的

  2. ruby-on-rails - 在 Rails 3 中向 Active Admin 添加全局导航项的最佳方法是什么 - 2

    我正在尝试将全局导航菜单项添加到我的ActiveAdmin安装(在“仪表板”导航按钮旁边)。ActiveAdmin说这在他们的网站上是可能的,但他们没有任何关于如何实现它的文档。有谁知道如何做到这一点?编辑:抱歉,我应该更清楚。我想添加一个指向由任意文本/链接对组成的全局导航的链接。IE,如果我想添加一个链接到http://google.com在事件管理员的全局导航中使用文本“Google”,我将如何实现? 最佳答案 ActiveAdmin.register_page"Google"domenu:priority=>1,:label

  3. 千耘农机导航的“星地一体”能力究竟是什么? - 2

    伴随农业机械化和智能化的发展,越来越多的人开始使用农机自动驾驶系统助力耕作,千耘农机导航的“星地一体”能力可有效解决信号受限的问题,实现作业提效。究竟什么是“星地一体”,又是如何解决智能化农机作业的痛点的?下面为大家揭秘。农机效率通常受限于通信网络目前虽然我国通讯网络的人口覆盖率达到99%,但地面移动通讯网络覆盖率仍小于国土面积的40%,而很多农田所在区域恰是山区、戈壁滩等偏远地区。两省交界地也会出现通信信号不稳定的状况;而国内大部分农机自动驾驶系统非常依赖通信网络,当通信网络弱的时候会出现系统掉线的现象,必须得携带小基站才能正常使用,极为繁琐。Q:什么是千耘农机导航“星地一体”能力?A:是星

  4. ruby-on-rails - 如何在不创建空模型的情况下创建 rails_admin 导航标签? - 2

    在railsadmin中,您可以像这样为模型及其子项定义导航标签:#inrails_admin.rbconfig.modelOrderdonavigation_label'Ordersrelated'endconfig.modelOrderProductsdoparentOrderend有没有办法在不创建模型的情况下向导航菜单添加标签(即仅用于分组)? 最佳答案 根据wiki,您可以像这样将静态链接附加到导航:RailsAdmin.configdo|config|config.navigation_static_links={'Go

  5. ruby - 为什么 Ruby 使用自己的安全导航运算符语法? - 2

    Ruby2.3.0引入了安全导航语法,它通过引入一个新的运算符来简化链式方法调用的nil处理,该运算符仅在先前语句的值不是nil。这是一个已经存在于C#、Groovy和Swift中的特性。例如inGroovy,语法是foo?.bar这基本上意味着结果值是foo.bar除非foo是null,在这种情况下返回值也是null因此不会抛出异常。还有C#(称为空条件运算符)和Swift(称为可选链接表达式)使用此表示法。所以语法在其他语言中似乎是相当标准的。现在,为什么在Ruby中语法是foo&.bar代替? 最佳答案 此答案基于thedis

  6. ruby - 如何在 Middleman 中生成导航? - 2

    我只是习惯了Middleman和一般的ruby。生成具有事件状态的导航的最佳方式是什么? 最佳答案 在当前版本的MM(2.x,尽管3.0接近)中,您可以通过向config.rb添加以下内容并在您的导航文件中进行一些调整来实现。这是aworkingversion以防我遗漏一些关键位:首先创建一个辅助函数:helpersdodefnav_active(page)@page_id==page?{:class=>"Active"}:{}endend然后,在navbarincludefile(在本例中它是一个haml文件)您可以使用nav_a

  7. ruby-on-rails - 在哪里可以找到高级 Ruby on Rails 教程? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我正在创建Rails应用程序,想知道在哪里可以找到好的有关如何使用Rails的教程。我使用了这个我认为非常适合开始学习Rails的博客:http://fairleads.blogspot.com/2007/12/rails-20-and-scaffolding-step-by-step.html我刚刚开始使用Rails,现在想学习更高级的Rails。

  8. ruby - 是否可以从功能文件导航到 VSCode 中的步骤定义 - 2

    我主要将RubyMine用于Cucumber/Ruby,现在,我开始使用VSCode,使用它可以运行和调试测试用例。我找不到从功能导航到步骤定义的方法。我尝试搜索扩展程序,但cucumber-step-mapper没有帮助。是否有任何配置可以实现从功能到步骤定义的导航? 最佳答案 您可以安装Cucumber(Gherkin)FullSupport来自VSCodeMarketplace的扩展:安装完成后,重新加载VSCode。现在为了使其适用于Ruby,您需要:按Ctrl+,打开用户设置向下滚动到CucumberAutoComplet

  9. Elasticsearch7.8.0版本入门—— 分页查询文档(高级查询) - 2

    目录一、初始化文档数据二、分页查询文档2.1、概述2.2、示例一、初始化文档数据在Postman中,向ES服务器发POST请求:http://localhost:9200/user/_doc/1,请求体内容为:{"name":"zhangsan","age":20,"sex":"男"}在Postman中,向ES服务器发POST请求:http://localhost:9200/user/_doc/2,请求体内容为:{"name":"zhangsan1","age":21,"sex":"男"}在Postman中,向ES服务器发POST请求:http://localhost:9200/user/_d

  10. 《MySQL高级篇》九、数据库的设计规范 - 2

    文章目录1.为什么需要数据库设计2.范式2.1范式简介2.2范式都包括哪些2.3键和相关属性的概念2.4第一范式(1stNF)2.5第二范式(2ndNF)2.6第三范式(3rdNF)2.7小结3.反范式化3.1概述3.2应用举例3.3反范式的新问题3.4反范式的适用场景4.BCNF(巴斯范式)5.第四范式6.第五范式、域键范式7.实战案例7.1迭代1次:考虑1NF7.2迭代2次:考虑2NF7.3迭代3次:考虑3NF7.4反范式化:业务优先的原则8.ER模型8.1ER模型包括哪些要素?8.2关系的类型8.3建模分析8.4ER模型的细化8.5ER模型图转换成数据表9.数据表的设计原则10.数据库对

随机推荐