热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Flutter第六章(BottomNavigationBar,AppBar,TabBar,TabController以及案例)

版权声明:本文为作者原创书籍。转载请注明作者和出处,未经授权,严禁私自转载,侵权必究!!!情感语录:如果你想得到从未拥有过的东西,那么你必须去做从未做过的事
版权声明:本文为作者原创书籍。转载请注明作者和出处,未经授权,严禁私自转载,侵权必究!!!

情感语录:如果你想得到从未拥有过的东西,那么你必须去做从未做过的事情。

欢迎来到本章节,上一章节我们讲了路由 还记得吗?知识点回顾 戳这里 Flutter基础第五章

本章主要围绕底部导航条顶部导航条 以及自定义AppBar 和优化方案TabController进行讲解,现在无论什么应用底部导航菜单和顶部导航菜单似乎都成了标配 ;有关这样的应用可以说是多不胜数”QQ、微信、头条、京东、饿了么等等…..”

本章简要:

1、BottomNavigationBar 底部导航条

2、 AppBar 自定义顶部样式

3、 TabBar 的样式配置

4、 TabController 的使用

一、BottomNavigationBar

BottomNavigationBar 是底部导航条,可以让我们定义底部 Tab 切换,BottomNavigationBar是 Scaffold组件的参数。抛开IOS不说,因为我是做Android开发的,在Android原生中你没有封装有自己的底部导航栏菜单模块,你可能最常用的就是 Activity + RadioButton + Fragment的方式去实现了,这对于刚入Android的新手来说,可能并没那么好切入,因为我在技术群里看到好多初学者都在问这样的问题。而在Flutter中这将变得轻松自如。

构造函数如下:

   BottomNavigationBar({
    Key key,
    @required this.items,
    this.onTap,
    this.currentIndex = 0,
    this.elevation = 8.0,
    BottomNavigationBarType type,
    Color fixedColor,
    this.backgroundColor,
    this.icOnSize= 24.0,
    Color selectedItemColor,
    this.unselectedItemColor,
    this.selectedIcOnTheme= const IconThemeData(),
    this.unselectedIcOnTheme= const IconThemeData(),
    this.selectedFOntSize= 14.0,
    this.unselectedFOntSize= 12.0,
    this.selectedLabelStyle,
    this.unselectedLabelStyle,
    this.showSelectedLabels = true,
    bool showUnselectedLabels,
  })
BottomNavigationBar 常用属性
    items List        底部导航条按钮集合
    
    iconSize                                   设置icon大小
    
    currentIndex                               默认选中第几个
    
    onTap                                      选中变化回调函数
    
    fixedColor                                 选中的颜色
    
    type                                       BottomNavigationBarType.fixed (固定类型)
    
                                               BottomNavigationBarType.shifting (流动类型)

                                               
    selectedLabelStyle                         选中时文本的样式

    unselectedLabelStyle                       未选中时文本的样式
                                               
    selectedFontSize                           选中时文本的大小            
                                               
    unselectedFontSize                         未选中时文本的大小    

    selectedItemColor                          选择中的颜色和 fixedColor互斥
    
    unselectedItemColor                        未选择中的颜色
    
    showUnselectedLabels                       是否显示未选中的文本标签

BottomNavigationBar的属性都大致了解了,下面我们来结合案例去实践,感受它妖娆的魅力吧O(∩_∩)O

本案例不会再按照以前的写法,把代码都写在main.dart 程序入口中,方便后面的文章写案例和查阅源码学习,在本章开始进行代码抽离。

案例要求: 利用上面的 BottomNavigationBar 组件实现类似微信手机端的底部菜单导航,点击底部导航菜单可以进行页面之间的切换。

首先我们先准备三个页面,主要用于点击底部导航菜单按钮,显示不同的页面效果,内容随便写点,有区分即可:

1、HomePage(主页)
  import 'package:flutter/material.dart';
  
  class HomePage extends StatefulWidget {
    HomePage({Key key}) : super(key: key);
  
    _HomePageState createState() => _HomePageState();
  }
  
  class _HomePageState extends State {
    @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.cyan,
        child: Center(child: Text("主页"),),
      );
    }
  }
2、CommunityPage(社区)
  import 'package:flutter/material.dart';
  
  class CommunityPage extends StatefulWidget {
    CommunityPage({Key key}) : super(key: key);
  
    _CommunityPageState createState() => _CommunityPageState();
  }
  
  class _CommunityPageState extends State {
    @override
    Widget build(BuildContext context) {
      return Container(
        color: Colors.green,
        child: Center(child: Text("社区"),),
      );
    }
  }
3、PersionPage(个人中心)
  import 'package:flutter/material.dart';
  
  class PersionPage extends StatefulWidget {
  
    PersionPage({Key key}) : super(key: key);
  
    _PersionPageState createState() => _PersionPageState();
  }
  
  class _PersionPageState extends State {
    @override
    Widget build(BuildContext context) {
        return Container(
        color: Colors.blue,
        child: Center(child: Text("个人中心"),),
      );
    }
  }
4、重点来了,新建Tabs.dart文件(名字随意,见名知意即可),按钮的点击有状态的改变,且要反应到视图模板上,这里我们应该使用 StatefulWidget,让Tabs类继承StatefulWidget:
  import 'package:flutter/material.dart';

  //引入准备好的界面
  import 'tabs/CommunityPage.dart';
  import 'tabs/PersionPage.dart';
  import 'tabs/HomePage.dart';

  
  
  class Tabs extends StatefulWidget {

    _TabsState createState() => _TabsState();

  }

  class _TabsState extends State {

    //默认选中的索引
    int _currentIndex=0;

    //将页面封装在集合中,方便通过索引取出
    List _pageList=[
      HomePage(),
      CommunityPage(),
      PersionPage(),
    ];


    @override
    Widget build(BuildContext context) {
      return Scaffold(
          appBar: AppBar(
            title: Text("呆萌"),
          ),
          body: this._pageList[this._currentIndex],

          bottomNavigationBar: BottomNavigationBar(

            //配置选中的索引值
            currentIndex: this._currentIndex,

            onTap: (int index){

              //改变状态
                setState(() {
                    this._currentIndex=index;
                });
            },

            //icon的大小
            iconSize:36.0,

            //选中的颜色
            fixedColor:Colors.red,

            selectedFontSize: 18,

            selectedLabelStyle: TextStyle(color: Colors.red),

            // selectedItemColor: Colors.red, 和 fixedColor互斥

            unselectedFontSize: 18,

            unselectedItemColor:Colors.deepPurple ,

            unselectedLabelStyle: TextStyle(color: Colors.deepPurple),

            showUnselectedLabels: true,

            //配置底部tabs为固定效果,即没有点击后的凸出感
            type:BottomNavigationBarType.fixed,

            // BottomNavigationBarItem 包装的底部按钮
            items: [

              BottomNavigationBarItem(

                icon: Icon(Icons.home),
                title: Text("首页")

              ),
               BottomNavigationBarItem(
                icon: Icon(Icons.question_answer),
                title: Text("社区")
              ),

               BottomNavigationBarItem(
                icon: Icon(Icons.people),
                title: Text("个人中心")
              )
            ],
          ),
        );
    }
  }

Tabs类中并没什么难点,部分也给出了介绍,值得注意的是 这里在点击事件 onTap中我们接收了一个点击后的索引值 并通过调用 setState()方法去改变了当前的索引值和界面的重新 build渲染视图,然后根据变化后的索引值重新在 _pageList 页面集合中取出对应的页面并赋值给 body,然而这就实现了页面切换效果的过程,第四章知识点还记得吗?戳这里回顾 StatefulWidget

5、接着在入口程序中将底部菜单进行引入
  import 'package:flutter/material.dart';
  import 'package:flutter_learn/page/Tabs.dart';


  void main() => runApp(MyApp());

  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
          home:Tabs(), // 返回 Tabs包装的菜单Widget
      );
    }
  }

运行效果见下图,还是挺简单的吧O(∩_∩)O

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
底部导航.gif

二、AppBar

AppBar中的属性较多,构造函数如下:

   AppBar({
    Key key,
    this.leading,
    this.automaticallyImplyLeading = true,
    this.title,
    this.actions,
    this.flexibleSpace,
    this.bottom,
    this.elevation,
    this.shape,
    this.backgroundColor,
    this.brightness,
    this.iconTheme,
    this.actionsIconTheme,
    this.textTheme,
    this.primary = true,
    this.centerTitle,
    this.titleSpacing = NavigationToolbar.kMiddleSpacing,
    this.toolbarOpacity = 1.0,
    this.bottomOpacity = 1.0,
  })
AppBar 常用属性:
    属性                         描述

    leading                      在标题前面显示的一个控件,在首页通常显示应用
                                 的 logo;在其他界面通常显示为返回按钮
                                 
    title                        标题,通常显示为当前界面的标题文字,可以放组件

    actions                      通常使用 IconButton 来表示,可以放按钮组

    bottom                       通常放 tabBar,标题下面显示一个 Tab 导航栏

    backgroundColor              导航背景颜色

    iconTheme                    图标样式

    textTheme                    文字样式

    centerTitle                  标题是否居中显示

AppBar在之前的案例中一直都有使用只是没有过多使用它的属性而已,现在介绍了,写个简单的页面来练习下。这里先不在上个案例中进行配置,新建一个 AppBarPage界面。

import 'package:flutter/material.dart';

class AppBarPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        //标题
        title: Text("呆萌"),
        //设置Bar背景色
        backgroundColor: Colors.red,
        //标题居中
        centerTitle: true,

        leading: Builder(
          builder: (BuildContext context) {
            return IconButton(

              icon: Icon(Icons.menu),

              onPressed: () {

                Scaffold.of(context)
                    .showSnackBar(SnackBar(content: new Text('点击了左侧按钮')));
              },
            );
          },
        ),
        actions: [
          IconButton(

            icon: Icon(Icons.search ,color: Colors.white,),
          ),
          IconButton(

            icon: Icon(Icons.settings,color: Colors.white,),
          )
        ],
      ),
      body: Center(
        child: Text(
          '这是AppBar测试界面',
          style: TextStyle(
            color: Colors.green,
            fontSize: 22,
          ),
        ),
      ),
    );
  }
}

首先是在AppBar左边leading 添加了一个 IconButton 并显示了一个菜单Icon,在点击的时候 弹出个SnackBar提示信息,SnackBar这里不具体讲,这个会在后面章节中详细介绍,需要注意的是当BuildContext在Scaffold之前时,调用Scaffold.of(context)会报错。这时可以通过Builder Widget来解决这个问题。其次通过actions添加了一组图片按钮,而actions接收的是一个List 集合,所以这里你可以放多个组件。

接下来配置路由,使得跳转可以到我们刚新建的AppBarPage页面中去。路由还记得吗?戳这里回顾 路由

 //配置路由
  final routes={
     //如有多个,请在这里添加即可。
    '/SecondPage':(context,{arguments})=>SecondPage(arguments:arguments),
    //让AppBarPage 做为launcher界面
    '/':(context)=>AppBarPage(),
  };

为了方便观看 AppBar 中添加的组件,这里使用 debugShowCheckedModeBanner:false把 debug 图标进行去掉。并在入口类中初始路由的时候去加载我们的 AppBarPage 页面

  import 'package:flutter/material.dart';
  import 'route/Routes.dart';


  void main() => runApp(MyApp());

  class MyApp extends StatelessWidget {

    @override
    Widget build(BuildContext context) {
      return MaterialApp(

          //去掉debug图标
          debugShowCheckedModeBanner:false ,

          //初始化的时候加载的路由
          initialRoute: '/',
          onGenerateRoute: onGenerateRoute

      );
    }
  }

运行看看效果吧:

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
AppBar(eg1).gif

效果还是不错吧,debug 图标也被我们成功的去掉了,这只是模拟器,在真设备上显示效果应该会更好,有没有觉得比原生实现起来简单很多呢?

三、TabBar

在Flutter中可以通过 TabBar 组件可以轻松实现顶部导航条,如不使用 TabBar 组件也是可以,比如通过Row组件去嵌套也是可以的,只是实现起来相对复杂很多。

构造函数如下:

  const TabBar({
    Key key,
    @required this.tabs,
    this.controller,
    this.isScrollable = false,
    this.indicatorColor,
    this.indicatorWeight = 2.0,
    this.indicatorPadding = EdgeInsets.zero,
    this.indicator,
    this.indicatorSize,
    this.labelColor,
    this.labelStyle,
    this.labelPadding,
    this.unselectedLabelColor,
    this.unselectedLabelStyle,
    this.dragStartBehavior = DragStartBehavior.start,
    this.onTap,
  })
TabBar 常用属性:
    属性                      描述

    tabs                      显示的标签内容,一般使用 Tab 对象,也可以是其他的Widget

    controller                TabController 对象

    isScrollable              是否可滚动

    indicatorColor            指示器颜色

    indicatorWeight           指示器高度

    indicatorPadding          底部指示器的 Padding

    indicator                 指示器 decoration,例如边框等

    indicatorSize             指示器大小计算方式,TabBarIndicatorSize.label 跟文字等宽,
                              TabBarIndicatorSize.tab 跟每个 tab 等宽
                              
    labelColor                选中 label 颜色

    labelStyle                选中 label 的 Style

    labelPadding              每个 label 的 padding 值

    unselectedLabelColor      未选中 label 颜色

    unselectedLabelStyle      未选中 label 的 Style

在上面介绍AppBar中有一个bottom属性刚好接收的就是 Widget 组件,TabBar也是一个组件,瞌睡遇到枕头啊!! 下面我们就来创建一个TabBar 组件将其插入。

  import 'package:flutter/material.dart';
  
  class AppBarPage extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return DefaultTabController(
        //这个一定的和tabs的子元素大小一致
        length: 3,
        
        child: Scaffold(
          appBar: AppBar(
            //标题
            title: Text("呆萌"),
            //设置Bar背景色
            backgroundColor: Colors.red,
            //标题居中
            centerTitle: true,
  
            bottom: TabBar(
  
              //配置指示器颜色
              indicatorColor: Colors.green,
              //让指示器和文字等宽
              indicatorSize: TabBarIndicatorSize.label,
              // 导航Tab
              tabs: [
                Tab(text: "视频"),
                Tab(text: "段子"), 
                Tab(text: "趣图")],
            ),
  
            leading: Builder(
              builder: (BuildContext context) {
                return IconButton(
                  icon: Icon(Icons.menu),
                  onPressed: () {
                    Scaffold.of(context)
                        .showSnackBar(SnackBar(content: new Text('点击了左侧按钮')));
                  },
                );
              },
            ),
            actions: [
              IconButton(
                icon: Icon(
                  Icons.search,
                  color: Colors.white,
                ),
              ),
              IconButton(
                icon: Icon(
                  Icons.settings,
                  color: Colors.white,
                ),
              )
            ],
          ),
          body: Container(child: Center(child: Text("测试TabBar"),),),
        ),
      );
    }
  }

这段代码中有个非常重要的配置 DefaultTabController 其中 length的大小一定等于 TabBar 中 tabs的子元素数量,否则报错。而 tabs 接收的是一个List 集合,在实际开发中,length往往需要动态配置。

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
TabBar(eg1).gif

可以看到我们实现了顶部菜单导航条,你可能马上会问,顶部导航是实现了,但我想点击顶部的菜单按钮后让下面空白区域跟随着进行页面联动,那该怎样实现呢? 想想下,Flutter中一个页面也是Widget,那我能不能给每个导航按钮绑定一个页面呢? 点击每个按钮就显示绑定的页面Widget即可!!

嘿嘿,确实是可以的,Flutter中也是这么做的并提供了 TabBarView 组件让我们去实现。

TabBarView构造函数:

  const TabBarView({
    Key key,
    @required this.children,
    this.controller,
    this.physics,
    this.dragStartBehavior = DragStartBehavior.start,
  }) 

TabBarView中 children 属性接收的也是一个List 那便不难看出:TabBar中的 tabs 的子元素和 TabBarView 中的子元素通过下标进行了一 一绑定。也就是说导航菜单有多少个按钮,TabBarView中就要准备多少个页面组件。基于这个原理我们把上面案例中的 body 替换成如下

   body: TabBarView(

      children: [
        Container(
          child: Center(
            child: Text("视频专区"),
          ),
        ),
        Container(
          child: Center(
            child: Text("段子专区"),
          ),
        ),
        Container(
          child: Center(
            child: Text("趣图专区"),
          ),
        )
       
      ],
    ),

运行试看下效果:

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
TabBarView.gif

果不其然,确实这样就实现了联动。是不是很激动?下面我来看一种情况:我们将顶部导航菜单增加到 7 个 甚至更多看看是个什么效果,添加之后注意修改 length 的长度 :

         // 导航Tab
          tabs: [
            Tab(text: "视频"),
            Tab(text: "段子"),
            Tab(text: "趣图"),

            Tab(text: "测试"),
            Tab(text: "测试"),
            Tab(text: "测试"),

            Tab(text: "测试"),
          ],
Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
TabBarView(eg2).gif

尼玛啊! 菜单被逐渐覆盖了,也就是说当前一屏的宽度不能够足以均分给这么多个导航菜单,导致了按钮不能完全显示出来!!那能不能让它能够自适应,如果有很多菜单,就让它能左右滑动呢? 当然可以 上面TabBar属性介绍中 isScrollable 就能让 TabBar 实现可以左右滑动。下面添加一个属性试试。

  import 'package:flutter/material.dart';
  
  class AppBarPage extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        //去掉debug图标
        debugShowCheckedModeBanner:false ,
  
        home: DefaultTabController(
          //这个一定的和tabs的子元素大小一致
          length: 7,
  
          child: Scaffold(
            appBar: AppBar(
              //标题
              title: Text("呆萌"),
              //设置Bar背景色
              backgroundColor: Colors.red,
              //标题居中
              centerTitle: true,
  
              bottom:  TabBar(
  
                //设置选中菜单文字颜色
                labelColor: Colors.white,
                //未选中文字菜单的颜色
                unselectedLabelColor: Colors.deepPurple,
  
  
                isScrollable: true,
                //配置指示器颜色
                indicatorColor: Colors.green,
                //让指示器和文字等宽
                indicatorSize: TabBarIndicatorSize.label,
                // 导航Tab
                tabs: [
                  Tab(text: "视频"),
                  Tab(text: "段子"),
                  Tab(text: "趣图"),
                  Tab(text: "测试"),
                  Tab(text: "测试"),
                  Tab(text: "测试"),
                  Tab(text: "测试"),
                ],
              ),
  
  
              leading: Builder(
                builder: (BuildContext context) {
                  return IconButton(
                    icon: Icon(Icons.menu),
                    onPressed: () {
                      Scaffold.of(context)
                          .showSnackBar(SnackBar(content: new Text('点击了左侧按钮')));
                    },
                  );
                },
              ),
              actions: [
                IconButton(
                  icon: Icon(
                    Icons.search,
                    color: Colors.white,
                  ),
                ),
                IconButton(
                  icon: Icon(
                    Icons.settings,
                    color: Colors.white,
                  ),
                )
              ],
            ),
            body: TabBarView(
              children: [
                Container(
                  child: Center(
                    child: Text("视频专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("段子专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("趣图专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("趣图专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("趣图专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("趣图专区"),
                  ),
                ),
                Container(
                  child: Center(
                    child: Text("趣图专区"),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }
  }

效果如下:

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
TabBarView(eg3).gif

特别需要注意的是在不知道顶部菜单具体有多少个的时候(尤其是菜单是根据服务器获取的情况)或者顶部有很多个菜单需要放置时一定得加上 isScrollable 属性。

此时你可能会说,感觉这样的方式实现好复杂,有没有像底部导航菜单那样更简单高效的实现方案啊? 当然是有的,请继续往下看。

三、TabController

上面的例子中 DefaultTabController 组件实现了AppBar里面的顶部导航切换,但是在项目中有数据请求,上拉加载更多等操作的时候,或者想在统一回调函数中处理点击菜单事件的监听,那么前面的写法,就不是很方便操作,因此,在flutter里面,还提供了一个用于实现顶部导航的组件 TabController

新建一个TabBarController.dart 页面 ,并继承 StatefulWidget 的有状态组件,并且实现 SingleTickerProviderStateMixin 这个类,这里用到了Dart 中的 mixin。你可以简单的理解就是通过 with 实现了多继承。

  import 'package:flutter/material.dart';
  
  class TabBarControllerPage extends StatefulWidget {
    TabBarControllerPage({Key key}) : super(key: key);
  
    _TabBarControllerPageState createState() => _TabBarControllerPageState();
  }
  
  class _TabBarControllerPageState extends State
      with SingleTickerProviderStateMixin {
  
    TabController _tabController;
  
    @override
    void dispose() {
      super.dispose();
      //在组件树中移除时销毁_tabController
      _tabController.dispose();
    }
  
    @override
    void initState() {
      super.initState();
      
      _tabCOntroller= new TabController(vsync: this, length: 4);
  
      //监听点击事件的回调
      _tabController.addListener(() {
  
        print( getView()[_tabController.index].key.toString());
  
      });
    }
  
    List getView() {
  
      List viewWidget = new List();
  
      //配置下key 方便日子看出 是否回调了 对应的菜单
      Tab tab = Tab(key: Key("video"), text: "视频");
      Tab tab1 = Tab(key: Key("Duan Zi"), text: "段子");
      Tab tab2 = Tab(key: Key("Pic"), text: "趣图");
      Tab tab3 = Tab(key: Key("Test"), text: "测试");
  
      viewWidget.add(tab);
      viewWidget.add(tab1);
      viewWidget.add(tab2);
      viewWidget.add(tab3);
  
      return viewWidget;
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("呆萌"),
          bottom: TabBar(
  
              //根据你的场景进行配置
              // isScrollable: true,
  
              //指示器颜色
              indicatorColor: Colors.red,
  
              //设置选中菜单文字颜色
              labelColor: Colors.white,
              //未选中文字菜单的颜色
              unselectedLabelColor: Colors.yellowAccent,
  
              //使得 TabBar 和 TabBarView之间进行关联,需要同时配置该对象 _tabController
              controller: this._tabController,
              tabs: getView()),
        ),
        body: TabBarView(
  
          controller: this._tabController,
          children: [
            Container(
              child: Center(
                child: Text("视频专区"),
              ),
            ),
            Container(
              child: Center(
                child: Text("段子专区"),
              ),
            ),
            Container(
              child: Center(
                child: Text("趣图专区"),
              ),
            ),
            Container(
              child: Center(
                child: Text("测试专区"),
              ),
            ),
          ],
        ),
      );
    }
  }

特别需要注意的是 在 TabController 依然是需要指定 tabs的长度,且 TabBarTabBarView 产生关联关系都是通过 controller 属性进行配置。

重新配置初始化路由到 TabBarControllerPage 界面,下面我们来运行看下效果。

Flutter第六章(BottomNavigationBar ,AppBar,TabBar ,TabController 以及案例)
TabController方案.gif

点击切换菜单按钮后控制台输出结果:

    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []
    I/flutter ( 2731): []

在回调中确实能获取到点击菜单按钮的后的下标,并通过下标取出了对应页面的Key值信息。在案例中明显可以看出 通过 TabController 方式去实现顶部导航菜单会更加简洁且灵活,因此开发中这样的需求我们应该多使用这种方式去实现。

好了本章节就此结束,又到了说再见的时候了,如果你喜欢请留下你的小红星,你们的支持才是创作的动力,如有错误,请热心的你留言指正, 谢谢大家观看,下章再会 O(∩_∩)O

实例源码地址: https://github.com/zhengzaihong/flutter_learn


推荐阅读
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了iOS开发中检测和解决内存泄漏的方法,包括静态分析、使用instruments检查内存泄漏以及代码测试等。同时还介绍了最能挣钱的行业,包括互联网行业、娱乐行业、教育行业、智能行业和老年服务行业,并提供了选行业的技巧。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 在springmvc框架中,前台ajax调用方法,对图片批量下载,如何弹出提示保存位置选框?Controller方法 ... [详细]
  • MVC设计模式的介绍和演化过程
    本文介绍了MVC设计模式的基本概念和原理,以及在实际项目中的演化过程。通过分离视图、模型和控制器,实现了代码的解耦和重用,提高了项目的可维护性和可扩展性。详细讲解了分离视图、分离模型和分离控制器的具体步骤和规则,以及它们在项目中的应用。同时,还介绍了基础模型的封装和控制器的命名规则。该文章适合对MVC设计模式感兴趣的读者阅读和学习。 ... [详细]
  • SpringBoot简单日志配置
     在生产环境中,只打印error级别的错误,在测试环境中,可以调成debugapplication.properties文件##默认使用logbacklogging.level.r ... [详细]
  • 【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
    2OpenvSwitch架构2.1OVS整体架构ovs-vswitchd:守护程序,实现交换功能,和Linux内核兼容模块一起,实现基于流的交换flow-basedswitchin ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • PHP设置MySQL字符集的方法及使用mysqli_set_charset函数
    本文介绍了PHP设置MySQL字符集的方法,详细介绍了使用mysqli_set_charset函数来规定与数据库服务器进行数据传送时要使用的字符集。通过示例代码演示了如何设置默认客户端字符集。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
author-avatar
罗文彬2502852027
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有