热门标签 | 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


推荐阅读
  • 本文回顾了2017年的转型和2018年的收获,分享了几家知名互联网公司提供的工作机会及面试体验。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • Python包管理工具pip的使用指南
    本文详细介绍了如何使用pip进行Python包的安装、管理和常见问题的解决方法,特别针对国内用户提供了优化建议。 ... [详细]
  • 本文将详细介绍如何在没有显示器的情况下,使用Raspberry Pi Imager为树莓派4B安装操作系统,并进行基本配置,包括设置SSH、WiFi连接以及更新软件源。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本篇文章介绍如何将两个分别表示整数的链表进行相加,并生成一个新的链表。每个链表节点包含0到9的数值,如9-3-7和6-3相加得到1-0-0-0。通过反向处理链表、逐位相加并处理进位,最终再将结果链表反向,即可完成计算。 ... [详细]
  • CentOS 系统管理基础
    本文介绍了如何在 CentOS 中查询系统版本、内核版本、位数以及磁盘分区的相关知识。通过这些命令,用户可以快速了解系统的配置和磁盘结构。 ... [详细]
  • ListView简单使用
    先上效果:主要实现了Listview的绑定和点击事件。项目资源结构如下:先创建一个动物类,用来装载数据:Animal类如下:packagecom.example.simplelis ... [详细]
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
  • Java中的基本数据类型与包装类解析
    本文探讨了Java编程语言中的8种基本数据类型及其对应的包装类。通过分析这些数据类型的特性和使用场景,以及自动拆装箱机制的实现原理,帮助开发者更好地理解和应用这些概念。 ... [详细]
  • vivo Y5s配备了联发科Helio P65八核处理器,这款处理器采用12纳米工艺制造,具备两颗高性能Cortex-A75核心和六颗高效能Cortex-A55核心。此外,它还集成了先进的图像处理单元和语音唤醒功能,为用户提供卓越的性能体验。 ... [详细]
  • 本文详细介绍了Java中实现异步调用的多种方式,包括线程创建、Future接口、CompletableFuture类以及Spring框架的@Async注解。通过代码示例和深入解析,帮助读者理解并掌握这些技术。 ... [详细]
  • 本文详细介绍了一种高效的算法——线性筛法,用于快速筛选出一定范围内的所有素数。通过该方法,可以显著提高求解素数问题的效率。 ... [详细]
  • 本文详细介绍了get和set方法的作用及其在编程中的实现方式,同时探讨了点语法的使用场景。通过具体示例,解释了属性声明与合成存取方法的概念,并补充了相关操作的最佳实践。 ... [详细]
  • Vue 开发与调试工具指南
    本文介绍了如何使用 Vue 调试工具,包括克隆仓库、安装依赖包、构建项目以及在 Chrome 浏览器中加载扩展的详细步骤。 ... [详细]
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社区 版权所有