Flutter实现底部菜单导航

简介

现在我们的 APP 上面都会在屏幕下方有一排的按钮,点击不同的按钮可以进入不同的界面。就是说在界面的底部会有一排的按钮导航。可看下面的图示。

完成图示

程序工程目录

梳理下实现步骤

我们需要实现这个底部菜单导航,就需要有底部菜单的那一排图标按钮。图标按钮是固定在一个工具栏 “bar” 上面。然后呢,需要分别需要有按钮对应的界面,就是说按钮有多少个,那么界面需要对应的有多少个。我们来一个清单列表:

  • 按钮图标区域。由于展示的方式都是一样的,我们需要有一个单独的控件,循环出来就好。
  • 工具栏区域。用于展示按钮图标,并且能固定在底部。
  • 首页。用于将工具栏放入界面中,并且将按钮对应的界面作为它的子元素存放于其中。
  • 不同的按钮对应的界面。在我们点击的图标按钮的时候,展示不同的界面。

我们底部的按钮是不会刷新的,界面会刷新,如何实现?

我们界面展示区域分为两块,一块展示底部的工具栏,一块展示页面。下面代码实现:

return new MaterialApp(
  home: new Scaffold(
   body: new Center(
    child: _currentPage // 动态的展示我们当前的页面
   ),
   bottomNavigationBar: bottomNavigationBar, // 底部工具栏
  ),

  theme: new ThemeData(
  primarySwatch: Colors.blue, // 设置主题颜色
  ),

 );

具体实现

第一步:创建一个 flutter 工程
可以按照工程目录图中的结构,将对应的文件建好。

第二步:修改 main.dart。
main.dart 是我们程序的入口。就类似于 Java、C 中的 main() ,作为一个程序的入口。我们将 main.dart 作为程序的启动入口,就不做过多的操作,只是指定去加载我们的首页(index.dart)。

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_demo/index/index.dart';   // 导入index.dart

// 这里为入口函数
void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
 // This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
  title: 'Flutter Demo',
  home: new Index(),  // 指定去加载 Index页面。
 );
 }
}

第三步:创建 NavigationIconView。
正如前面说的,我们底部的按钮区域展示的图标加上文字是固定格式,所以将这一部分抽取出来,作为一个公共的 class,方便界面程序维护。

navigation_icon_view.dart

import 'package:flutter/material.dart';

// 创建一个 Icon 展示控件
class NavigationIconView {

 // 创建两个属性,一个是 用来展示 icon, 一个是动画处理
 final BottomNavigationBarItem item;
 final AnimationController controller;

 // 类似于 java 中的构造方法
 // 创建 NavigationIconView 需要传入三个参数, icon 图标,title 标题, TickerProvider
 NavigationIconView({Widget icon, Widget title, TickerProvider vsync}):
 item = new BottomNavigationBarItem(
  icon: icon,
  title: title,
 ),
 controller = new AnimationController(
  duration: kThemeAnimationDuration, // 设置动画持续的时间
  vsync: vsync       // 默认属性和参数
 );
}

第四步:创建 Index

这一步就比较重要了,因为我们需要在这个界面上面去布局,以及实现点击按钮图标之后,有事件触发。正因为我们需要有事件触发,所以创建一个带有状态的 Widget(StatefulWidget)。下面的代码注释给的很详细了,可以仔细看。

index.dart

import 'package:flutter/material.dart';
import 'package:flutter_demo/NoticePage/notice_page.dart';
import 'package:flutter_demo/home/home_page.dart';
import 'package:flutter_demo/idea/idea_page.dart';
import 'package:flutter_demo/market/market_page.dart';
import 'package:flutter_demo/my/my_page.dart';

import 'navigation_icon_view.dart'; // 如果是在同一个包的路径下,可以直接使用对应的文件名

// 创建一个 带有状态的 Widget Index
class Index extends StatefulWidget {

 // 固定的写法
 @override
 State<StatefulWidget> createState() => new _IndexState();
}

// 要让主页面 Index 支持动效,要在它的定义中附加mixin类型的对象TickerProviderStateMixin
class _IndexState extends State<Index> with TickerProviderStateMixin{

 int _currentIndex = 0; // 当前界面的索引值
 List<NavigationIconView> _navigationViews; // 底部图标按钮区域
 List<StatefulWidget> _pageList; // 用来存放我们的图标对应的页面
 StatefulWidget _currentPage; // 当前的显示页面

 // 定义一个空的设置状态值的方法
 void _rebuild() {
 setState((){});
 }

 @override
 void initState() {
 super.initState();

 // 初始化导航图标
 _navigationViews = <NavigationIconView>[
  new NavigationIconView(icon: new Icon(Icons.assessment), title: new Text("首页"), vsync: this), // vsync 默认属性和参数
  new NavigationIconView(icon: new Icon(Icons.all_inclusive), title: new Text("想法"), vsync: this),
  new NavigationIconView(icon: new Icon(Icons.add_shopping_cart), title: new Text("市场"), vsync: this),
  new NavigationIconView(icon: new Icon(Icons.add_alert), title: new Text("通知"), vsync: this),
  new NavigationIconView(icon: new Icon(Icons.perm_identity), title: new Text("我的"), vsync: this),
 ];

 // 给每一个按钮区域加上监听
 for (NavigationIconView view in _navigationViews) {
  view.controller.addListener(_rebuild);
 }

 // 将我们 bottomBar 上面的按钮图标对应的页面存放起来,方便我们在点击的时候
 _pageList = <StatefulWidget>[
  new HomePage(),
  new IdeaPage(),
  new MarketPage(),
  new NoticePage(),
  new MyPage()
 ];
 _currentPage = _pageList[_currentIndex];
 }

 @override
 Widget build(BuildContext context) {

 // 声明定义一个 底部导航的工具栏
 final BottomNavigationBar bottomNavigationBar = new BottomNavigationBar(
  items: _navigationViews
   .map((NavigationIconView navigationIconView) => navigationIconView.item)
   .toList(), // 添加 icon 按钮
  currentIndex: _currentIndex, // 当前点击的索引值
  type: BottomNavigationBarType.fixed, // 设置底部导航工具栏的类型:fixed 固定
  onTap: (int index){ // 添加点击事件
  setState((){ // 点击之后,需要触发的逻辑事件
   _navigationViews[_currentIndex].controller.reverse();
   _currentIndex = index;
   _navigationViews[_currentIndex].controller.forward();
   _currentPage = _pageList[_currentIndex];
  });
  },
 );

 return new MaterialApp(
  home: new Scaffold(
   body: new Center(
    child: _currentPage // 动态的展示我们当前的页面
   ),
   bottomNavigationBar: bottomNavigationBar, // 底部工具栏
  ),

  theme: new ThemeData(
  primarySwatch: Colors.blue, // 设置主题颜色
  ),

 );
 }

}

第四步:创建页面

前面的步骤都是在搭建我们的基础,现在是做展示界面。由于不同的界面,对应的源码都是和下面的是一样的,只是 class 的名字不一样,就都可以使用同样的模版复制过去就有可以了。

home_page.dart

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget{
 @override
 State<StatefulWidget> createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {

 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
  home: new Scaffold(
  appBar: new AppBar(
   title: new Text('首页'),
   actions: <Widget>[
   new Container()
   ],
  ),
  body: new Center(
   child: null,
  ),
  ),
 );
 }
}

idea_page.dart

import 'package:flutter/material.dart';

class IdeaPage extends StatefulWidget{
 @override
 State<StatefulWidget> createState() => new _IdeaPageState();
}
class _IdeaPageState extends State<IdeaPage> {

 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
  home: new Scaffold(
  appBar: new AppBar(
   title: new Text('想法'),
   actions: <Widget>[
   new Container()
   ],
  ),
  body: new Center(
   child: null,
  ),
  ),
 );
 }
}

market_page.dart

import 'package:flutter/material.dart';
class MarketPage extends StatefulWidget{
 @override
 State<StatefulWidget> createState() => new _MarketPageState();
}
class _MarketPageState extends State<MarketPage> {
 @override
 Widget build(BuildContext context) {
 return new MaterialApp(
  home: new Scaffold(
  appBar: new AppBar(
   title: new Text('市场'),
   // 后面的省略
   // ......
  )
  ),
 );
 }

}

剩下的界面都是一样子的了,就不贴出来了,都是复制一下,改了一个类名,和显示的文字而已。

第五步:启动测试

到此我们就完成了,可以启动程序,看下效果。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Flutter实现底部导航栏

    本文实例为大家分享了Flutter实现底部导航栏的具体代码,供大家参考,具体内容如下 效果 实现 先将自动生成的main.dart里面的代码删除, import 'package:flutter/material.dart'; import 'package:flutter_guohe/pages/main.dart'; void main() { runApp(new Guohe()); } 创建app.dart作为首页的页面文件 class Guohe extends StatefulWid

  • Flutter底部导航栏的实现方式

    本文实例为大家分享了Flutter底部导航栏的实现代码,供大家参考,具体内容如下 老规格,先看图: 程序主结构如下: 1.在程序主入口文件main.dart添加如下代码 import 'package:flutter/material.dart'; import 'bottom_navigation.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build

  • flutter BottomAppBar实现不规则底部导航栏

    本文实例为大家分享了flutter实现不规则底部导航栏的具体代码,供大家参考,具体内容如下 实现底部导航栏并点击切换页面可简述为有三种方式 TabBar + TabBarView BottomNavigationBar + BottomNavigationBarItem 自定义 BottomAppBar 在这里 使用 BottomAppBar 来实现 /** * 有状态StatefulWidget * 继承于 StatefulWidget,通过 State 的 build 方法去构建控件 */

  • Flutter质感设计之底部导航

    BottomNavigationBar即底部导航栏控件.显示在应用底部的质感设计控件,用于在少量视图中切换.底部导航栏包含多个以标签.图标或两者搭配的形式显示在项目底部的项目,提供了应用程序的顶级视图之间的快速导航.对于较大的屏幕,侧面导航可能更好. 创建navigation_icon_view.dart文件,定义一个NavigationIconView类,用于管理BottomNavigationBarItem(底部导航栏项目)控件的样式.行为与动画. import 'package:flutt

  • Flutter实现底部导航栏效果

    大家最近都在讨论新鲜技术-flutter,小编也在学习中,遇到大家都遇到的问题,底部导航.下面给大家贴出底部导航的编写,主要参考了lime这个项目. 上代码 一.在main.dart文件中 定义APP的基本信息 class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new

  • Flutter实现底部导航

    本文实例为大家分享了Flutter实现底部导航的具体代码,供大家参考,具体内容如下 BottomNavigationBar使用 底部导航栏 主文件 main.dart (注意导入文件路径) import 'package:flutter/material.dart'; import './views/firstPage.dart'; import './views/secondPage.dart'; import './views/thirdPage.dart'; //首先导入三个界面 void

  • Flutter底部不规则导航的实现过程

    前言 本文主要介绍的是关于Flutter实现底部不规则导航的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 实现方法: 1.main.dart文件 import 'package:flutter/material.dart'; import 'bootom_appBar.dart'; void main () =>runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(B

  • Flutter实现底部菜单导航

    简介 现在我们的 APP 上面都会在屏幕下方有一排的按钮,点击不同的按钮可以进入不同的界面.就是说在界面的底部会有一排的按钮导航.可看下面的图示. 完成图示 程序工程目录 梳理下实现步骤 我们需要实现这个底部菜单导航,就需要有底部菜单的那一排图标按钮.图标按钮是固定在一个工具栏 "bar" 上面.然后呢,需要分别需要有按钮对应的界面,就是说按钮有多少个,那么界面需要对应的有多少个.我们来一个清单列表: 按钮图标区域.由于展示的方式都是一样的,我们需要有一个单独的控件,循环出来就好. 工

  • flutter实现底部不规则导航栏

    本文实例为大家分享了flutter实现底部不规则导航栏的具体代码,供大家参考,具体内容如下 scafford的bottomNavigationBar参数赋值BottomAppBar可以实现,BottomAppBar比BottomNavigationBar灵活,在body参数之外准备好一个fab,使用BottomAppBar的shape属性设置BottomAppBar为一个挖了圆形的矩形,设置fab的位置便可: main: import 'package:flutter/cupertino.dar

  • Android使用开源组件PagerBottomTabStrip实现底部菜单和顶部导航功能

    PagerBottomTabStrip 是一个基本按谷歌Material Design规范完成的安卓底部导航栏控件 官方设计规范:https://www.google.com/design/spec/components/bottom-navigation.html 1.前言 (1)底部选择菜单功能应该是大多app都会用到的,实现方式也有很多种,比较笨的方法可以自定义一个xml,下方布局样式,每次点击不同按钮时跳转到不同activity,这个activity重新加载一下底部菜单 (2)今天介绍一

  • Flutter沉浸式状态栏/AppBar导航栏/仿咸鱼底部凸起导航栏效果

    如下图:状态栏是指android手机顶部显示手机状态信息的位置. android 自4.4开始新加入透明状态栏功能,状态栏可以自定义颜色背景,使titleBar能够和状态栏融为一体,增加沉浸感. 如上图Flutter状态栏默认为黑色半透明,那么如何去掉这个状态栏的黑色半透明背景色,让其和标题栏颜色一致,通栏沉浸式,实现如下图效果呢?且继续看下文讲述. 在flutter项目目录下找到android主入口页面MainActivity.kt或MainActivity.java,判断一下版本号然后将状态

  • Flutter实现底部导航栏创建详解

    目录 添加依赖项 如何使用 功能 属性 主题 预览图 代码 Flutter web问题:Failed to load network image 我的解决办法 参考资料 ConvexBottomBar是一个底部导航栏组件,用于展现凸起的TAB效果,支持多种内置样式与动画交互.你可以在https://appbar.codemagic.app/上找到在线样例. 添加依赖项 在你的项目中去 pubspec.添加依赖项: 添加https://pub.dev/packages/convex_bottom_

  • flutter实现底部导航栏切换

    本文实例为大家分享了flutter实现底部导航栏切换的具体代码,供大家参考,具体内容如下 思路:MaterialApp是提供了bottomnavigationbar的,可以使用,这个已经提供了的widget,再利用每次点击tab的时候使用set state方法来更新屏幕,切换中间的body的widget:main文件: import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import '

  • Flutter自定义底部导航栏的方法

    本文实例为大家分享了Flutter自定义底部导航栏的具体代码,供大家参考,具体内容如下 文件结构: main.dart import 'package:flutter/material.dart'; import 'pages/tabs.dart';   void main() => runApp(new MyApp());   class MyApp extends StatelessWidget {   @override   Widget build(BuildContext contex

随机推荐