Flutter质感设计之底部导航

BottomNavigationBar即底部导航栏控件。显示在应用底部的质感设计控件,用于在少量视图中切换。底部导航栏包含多个以标签、图标或两者搭配的形式显示在项目底部的项目,提供了应用程序的顶级视图之间的快速导航。对于较大的屏幕,侧面导航可能更好。

创建navigation_icon_view.dart文件,定义一个NavigationIconView类,用于管理BottomNavigationBarItem(底部导航栏项目)控件的样式、行为与动画。

import 'package:flutter/material.dart';
// 创建类,导航图标视图
class NavigationIconView {
 // 导航图标视图的构造函数
 NavigationIconView({
  // 控件参数,传递图标
  Widget icon,
  // 控件参数,传递标题
  Widget title,
  // 控件参数,传递颜色
  Color color,
  /*
   * Ticker提供者
   * 由类实现的接口,可以提供Ticker对象
   *  Ticker对象:每个动画帧调用它的回调一次
   */
  TickerProvider vsync,
 }):_icon = icon, //接收传递的图标
  // 接收传递的颜色
  _color = color,
  // 创建底部导航栏项目
  item = new BottomNavigationBarItem(
   // 项目的图标
   icon: icon,
   // 项目的标题
   title: title
  ),
  // 创建动画控制器
  controller = new AnimationController(
   // 动画持续的时间长度:默认情况下主题更改动画的持续时间
   duration: kThemeAnimationDuration,
   // 垂直同步
   vsync: vsync,
  ) {
   // 创建曲线动画
   _animation = new CurvedAnimation(
    // 应用曲线动画的动画
    parent: controller,
    /*
     * 正向使用的曲线:
     * 从0.5
     * 到1.0结束
     * 应用的曲线:快速启动并缓和到最终位置的曲线
     */
    curve: new Interval(0.5, 1.0, curve: Curves.fastOutSlowIn),
   );
  }
 // 类成员,存储图标
 final Widget _icon;
 // 类成员,存储颜色
 final Color _color;
 // 类成员,底部导航栏项目
 final BottomNavigationBarItem item;
 // 类成员,动画控制器
 final AnimationController controller;
 // 类成员,曲线动画
 CurvedAnimation _animation;
 /*
  * 类函数,过渡转换
  * BottomNavigationBarType:定义底部导航栏的布局和行为
  * BuildContext:处理控件树中的控件
  */
 FadeTransition transition(BottomNavigationBarType type, BuildContext context) {
  // 局部变量,存储图标颜色
  Color iconColor;
  // 如果底部导航栏的位置和大小在点击时会变大
  if (type == BottomNavigationBarType.shifting) {
   // 存储颜色作为图标颜色
   iconColor = _color;
  } else {
   /*
    * 保存质感设计主题的颜色和排版值:
    * 使用ThemeData来配置主题控件
    * 使用Theme.of获取当前主题
    */
   final ThemeData themeData = Theme.of(context);
   /*
    * 如果程序整体主题的亮度很高(需要深色文本颜色才能实现可读的对比度)
    * 就返回程序主要部分的背景颜色作为图标颜色
    * 否则返回控件的前景颜色作为图标颜色
    */
   iconColor = themeData.brightness == Brightness.light
    ? themeData.primaryColor
    : themeData.accentColor;
  }
  // 返回值,创建不透明度转换
  return new FadeTransition(
   // 控制子控件不透明度的动画
   opacity: _animation,
   // 子控件:创建滑动转换过渡
   child: new SlideTransition(
    /*
     * 控制子控件位置的动画
     * 开始值和结束值之间的线性插值<以尺寸的分数表示的偏移量>
     *  (1.0,0.0)表示Size的右上角
     *  (0.0,1.0)表示Size的左下角
     */
    position: new Tween<FractionalOffset>(
     // 此变量在动画开头的值
     begin: const FractionalOffset(0.0, 0.02),
     // 此变量在动画结尾处的值:左上角
     end: FractionalOffset.topLeft,
    ).animate(_animation), // 返回给定动画,该动画接受由此对象确定的值
    // 子控件:创建控制子控件的颜色,不透明度和大小的图标主题
    child: new IconTheme(
     // 用于子控件中图标的颜色,不透明度和大小
     data: new IconThemeData(
      // 图标的默认颜色
      color: iconColor,
      // 图标的默认大小
      size: 120.0,
     ),
     // 子控件
     child: _icon,
    )
   )
  );
 }
}

再创建main.dart文件。类CustomIcon创建一个容器控件,作为一个自定义的图标使用。同时使用质感设计的弹出菜单控件切换底部导航栏的行为和样式。

import 'package:flutter/material.dart';
import 'navigation_icon_view.dart';
// 创建类,自定义图标,继承StatelessWidget(无状态的控件)
class CustomIcon extends StatelessWidget {
 // 覆盖此函数以构建依赖于动画的当前状态的控件
 @override
 Widget build(BuildContext context) {
  // 获取当前图标主题,创建与此图标主题相同的图标主题
  final IconThemeData iconTheme = IconTheme.of(context).fallback();
  // 返回值,创建一个容器控件
  return new Container(
   // 围绕子控件的填充:每个边都偏移4.0
   margin: const EdgeInsets.all(4.0),
   // 容器宽度:图标主题的宽度减8.0
   width: iconTheme.size - 8.0,
   // 容器高度:图标主题的高度减8.0
   height: iconTheme.size - 8.0,
   // 子控件的装饰:创建一个装饰
   decoration: new BoxDecoration(
    // 背景颜色:图标主题的颜色
    backgroundColor: iconTheme.color
   )
  );
 }
}
// 创建类,菜单演示,继承StatefulWidget(有状态的控件)
class MenusDemo extends StatefulWidget {
 /*
  * 覆盖具有相同名称的超类成员
  * createState方法在树中的给定位置为此控件创建可变状态
  * 子类应重写此方法以返回其关联的State子类新创建的实例
  */
 @override
 _MenusDemoState createState() => new _MenusDemoState();
}
/*
 * 关联State子类的实例
 * 继承State:StatefulWidget(有状态的控件)逻辑和内部状态
 * 继承TickerProviderStateMixin,提供Ticker对象
 */
class _MenusDemoState extends State<MenusDemo> with TickerProviderStateMixin {
 // 类成员,存储底部导航栏的当前选择
 int _currentIndex = 2;
 // 类成员,存储底部导航栏的布局和行为:在点击时会变大
 BottomNavigationBarType _type = BottomNavigationBarType.shifting;
 // 类成员,存储NavigationIconView类的列表
 List<NavigationIconView> _navigationViews;
 /*
  * 在对象插入到树中时调用
  * 框架将为它创建的每个State(状态)对象调用此方法一次
  * 覆盖此方法可以实现此对象被插入到树中的位置的初始化
  * 或用于配置此对象上的控件的位置的初始化
  */
 @override
 void initState() {
  // 调用父类的内容
  super.initState();
  // 在存储NavigationIconView类的列表里添加内容
  _navigationViews = <NavigationIconView>[
   /*
    * 创建NavigationIconView类的实例
    * 传递图标参数
    * 传递标题参数
    * 传递颜色参数
    * 传递Ticker对象
    */
   new NavigationIconView(
    icon: new Icon(Icons.access_alarm),
    title: new Text('成就'),
    color: Colors.deepPurple[500],
    vsync: this,
   ),
   new NavigationIconView(
    icon: new CustomIcon(),
    title: new Text('行动'),
    color: Colors.deepOrange[500],
    vsync: this,
   ),
   new NavigationIconView(
    icon: new Icon(Icons.cloud),
    title: new Text('人物'),
    color: Colors.teal[500],
    vsync: this,
   ),
   new NavigationIconView(
    icon: new Icon(Icons.favorite),
    title: new Text('财产'),
    color: Colors.indigo[500],
    vsync: this,
   ),
   new NavigationIconView(
    icon: new Icon(Icons.event_available),
    title: new Text('设置'),
    color: Colors.pink[500],
    vsync: this,
   ),
  ];
  // 循环调用存储NavigationIconView类的列表的值
  for (NavigationIconView view in _navigationViews)
   // 每次动画控制器的值更改时调用侦听器
   view.controller.addListener(_rebuild);
  // 底部导航栏当前选择的动画控制器的值为1.0
  _navigationViews[_currentIndex].controller.value = 1.0;
 }
 // 释放此对象使用的资源
 @override
 void dispose() {
  // 调用父类的内容
  super.dispose();
  // 循环调用存储NavigationIconView类的列表中的项
  for (NavigationIconView view in _navigationViews)
   // 调用此方法后,对象不再可用
   view.controller.dispose();
 }
 // 动画控制器的值更改时的操作
 void _rebuild() {
  // 通知框架此对象的内部状态已更改
  setState((){
   // 重建,以便为视图创建动画
  });
 }
 // 建立过渡堆栈
 Widget _buildTransitionsStack() {
  // 局部变量,存储不透明度转换的列表
  final List<FadeTransition> transitions = <FadeTransition>[];
  // 循环调用存储NavigationIconView类的列表的值
  for (NavigationIconView view in _navigationViews)
   // 在存储不透明度转换的列表中添加transition函数的返回值
   transitions.add(view.transition(_type, context));
  // 对存储不透明度转换的列表进行排序
  transitions.sort((FadeTransition a, FadeTransition b) {
   final Animation<double> aAnimation = a.listenable;
   final Animation<double> bAnimation = b.listenable;
   // aValue:a的动画值
   double aValue = aAnimation.value;
   // bValue:b的动画值
   double bValue = bAnimation.value;
   /*
    * 将aValue与bValue进行比较
    * 返回一个负整数,aValue排序在bValue之前
    * 返回一个正整数,aValue排序在bValue之后
    */
   return aValue.compareTo(bValue);
  });
  // 返回值,创建层叠布局控件
  return new Stack(children: transitions);
 }
 // 覆盖此函数以构建依赖于动画的当前状态的控件
 @override
 Widget build(BuildContext context) {
  // 局部变量,创建底部导航栏
  final BottomNavigationBar botNavBar = new BottomNavigationBar(
   /*
    * 在底部导航栏中布置的交互项:迭代存储NavigationIconView类的列表
    * 返回此迭代的每个元素的底部导航栏项目
    * 创建包含此迭代的元素的列表
    */
   items: _navigationViews
    .map((NavigationIconView navigationView) => navigationView.item)
    .toList(),
   // 当前活动项的索引:存储底部导航栏的当前选择
   currentIndex: _currentIndex,
   // 底部导航栏的布局和行为:存储底部导航栏的布局和行为
   type: _type,
   // 当点击项目时调用的回调
   onTap: (int index) {
    // 通知框架此对象的内部状态已更改
    setState((){
     // 当前选择的底部导航栏项目,开始反向运行此动画
     _navigationViews[_currentIndex].controller.reverse();
     // 更新存储底部导航栏的当前选择
     _currentIndex = index;
     // 当前选择的底部导航栏项目,开始向前运行此动画
     _navigationViews[_currentIndex].controller.forward();
    });
   }
  );
  // 实现基本的质感设计视觉布局结构
  return new Scaffold(
   // 质感设计应用栏
   appBar: new AppBar(
    // 应用栏中显示的主要控件,包含程序当前内容描述的文本
    title: new Text('底部导航演示'),
    // 在标题控件后显示的控件
    actions: <Widget> [
     // 创建一个显示弹出式菜单的按钮
     new PopupMenuButton<BottomNavigationBarType>(
      // 当用户从此按钮创建的弹出菜单中选择一个值时调用
      onSelected: (BottomNavigationBarType value) {
       // 通知框架此对象的内部状态已更改
       setState((){
        // 存储底部导航栏的布局和行为:选择值
        _type = value;
       });
      },
      // 点击弹出菜单中显示的项目时调用
      itemBuilder: (BuildContext context) => <PopupMenuItem<BottomNavigationBarType>> [
       /*
        * 弹出菜单中的显示项目
        * 返回值:底部导航栏的布局和行为
        * 子控件:文本控件
        */
       new PopupMenuItem<BottomNavigationBarType>(
        value: BottomNavigationBarType.fixed,
        child: new Text('Fixed')
       ),
       new PopupMenuItem<BottomNavigationBarType>(
        value: BottomNavigationBarType.shifting,
        child: new Text('Shifting')
       )
      ]
     )
    ]
   ),
   // 主要内容
   body: new Center(
    // 主要内容:_buildTransitionsStack函数的返回值
    child: _buildTransitionsStack()
   ),
   // 水平的按钮数组,沿着程序的底部显示
   bottomNavigationBar: botNavBar,
  );
 }
}
// 程序入口
void main() {
 // 创建质感设计程序,并放置到主屏幕
 runApp(new MaterialApp(
  // 在窗口管理器中使用此应用程序的单行描述
  title: 'Flutter教程',
  // 程序的默认路由的控件
  home: new MenusDemo(),
 ));
}

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

(0)

相关推荐

  • 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实现底部导航栏

    本文实例为大家分享了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 BottomAppBar实现不规则底部导航栏

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

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

  • Flutter实现底部菜单导航

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

  • 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质感设计之底部导航

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

  • Flutter质感设计之持久底部面板

    持久性底部面板可以用于补充应用主要内容的信息,即使用户与应用程序的其他控件进行互动,也仍然可以看到持久的底部面板.可以使用Scaffold.showBottomSheet函数创建和显示持久性底部面板. import 'package:flutter/material.dart'; class MyApp extends StatefulWidget { @override _MyApp createState() => new _MyApp(); } class _MyApp extends S

  • Flutter质感设计之模态底部面板

    模态底部面板是菜单或对话框的替代方案,可防止用户与其他控件进行互动,可以使用showModalBottomSheet函数创建和显示模态底部面板. import 'package:flutter/material.dart'; class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new

  • Flutter质感设计之直接输入

    Input控件是质感设计的文本输入控件,它在用户每次输入时都会调用onChanged回调时,都会更新字段值,还可以实时的对用户输入进行响应. import 'package:flutter/material.dart'; class MyApp extends StatefulWidget { @override _MyApp createState() => new _MyApp(); } class _MyApp extends State<MyApp> { // InputValu

  • Flutter质感设计之进度条

    LinearProgressIndicator控件是质感设计中的线性进度指示器,具体内容如下 import 'package:flutter/material.dart'; class ActionViewEcology extends StatelessWidget { /* * 构建函数,传递参数 * 最大能量值 * 最大饥饿值 * 最大情绪值 * 当前能量值 * 当前饥饿值 * 当前情绪值 */ ActionViewEcology({ this.maximumEmergy, this.ma

  • Flutter质感设计之表单输入

    FormField控件是单一表单字段,这个控件维护表单字段的当前状态,以便更新和验证错误能在UI中可见.TextField控件就是在FormField中包装了一个Input控件(后面的文章讲解),FormField维护输入的当前值,使您不需要自己管理它,更容易一次保存,重置或验证多个字段. import 'package:flutter/material.dart'; class MyApp extends StatefulWidget { @override _MyApp createStat

  • Flutter质感设计之弹出菜单

    PopupMenuButton控件即弹出菜单控件,点击控件会出现菜单. import 'package:flutter/material.dart'; class MenusDemo extends StatefulWidget { @override _MenusDemoState createState() => new _MenusDemoState(); } class _MenusDemoState extends State<MenusDemo> { String _body

  • Flutter质感设计之列表项

    本文为大家分享了Flutter实现列表项的具体代码,供大家参考,具体内容如下 创建achievement_view_list_item.dart文件,具体的实现每一个列表项. import 'package:flutter/material.dart'; // 创建类,成就目标 class Target { // 常量,构建函数 const Target({ // 自变量,目标名称 this.name, // 自变量,目标奖励 this.reward }); // 最终值,成就目标名称 fina

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

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

随机推荐