在上面的代码中,`TabBar` 用于生成一个 `Tab` 菜单, `TabController` 用于控制/监听 `Tab` 菜单的切换,`Tab` 组件代表一个菜单,定义如下:

Tab({

Key key,

this.text, // 菜单文本

this.icon, // 菜单图标

this.child, // 自定义组件样式

})


[](

)`TabBarView`

-------------------------------------------------------------------------------

通过上面的 `TabBar` 只能生成一个静态的菜单,`Tab` 菜单和 `Tab` 页面切换需要同步,然而实现这一功能的就需要通过 `TabBarView` 组件了。`TabBarView` 组件不仅可以轻松实现 `Tab` ,而且可以非常容易配合 `TabBar` 来实现同步切换和滑动状态同步。示例:

class _HomeContentState extends State<HomeContent> with SingleTickerProviderStateMixin{

TabController _tabController;

List tabs = ["新闻","历史","图片"];

void initState(){

super.initState();

_tabController = TabController(length: tabs.length, vsync: this);

}

@override

Widget build(BuildContext context) {

return Scaffold(

  appBar: AppBar(

    //抽屉菜单

    leading: Builder(builder: (context){

      return IconButton(

          icon: Icon(Icons.dashboard,color:Colors.white),

          onPressed: (){},

        );

    },),

    //标题

    title: Text('导航栏'),

    //导航栏右侧菜单

    actions: <Widget>[

      IconButton(

        icon: Icon(Icons.share),

        onPressed: (){},

      )

    ],

    //导航栏底部Tab

    bottom: TabBar(

      controller: _tabController,

      tabs: tabs.map((item) => Tab(text: item)).toList()

    ),

  ),

  body: TabBarView(

    controller: _tabController,

    children: tabs.map((e){

      return Container(

        alignment: Alignment.center,

        child: Text(e,textScaleFactor:5),

      );

    }).toList(),

  ),

);

}

}


运行项目后发现效果出来了,无论是点击导航按钮还是手势滑动屏幕,都实现了切换导航的功能。那么,他们是如何同步的呢?答案是:同一个 `controller`,在上面的例子中,导航 `TabBar` 中的 `controller` 和 `TabBarView` 中的 `controller` 是同一个对象。

[](

)抽屉菜单

-----------------------------------------------------------------------

`Scaffold` 组件提供了 `drawer` 、`endDrawer` 两个属性用于表示一个页面的左、右抽屉菜单。示例:

class MyDrawer extends StatelessWidget{

const MyDrawer({Key key}) : super(key:key);

@override

Widget build(BuildContext context) {

return Drawer(

  child: MediaQuery.removePadding(//用于移除Drawer默认的留白

    context: context,

    removeTop: true,

    child: Column(

      crossAxisAlignment: CrossAxisAlignment.start,

      children: <Widget>[

        Padding(

          padding: const EdgeInsets.only(top: 38),

          child: Row(

            children: <Widget>[

              Padding(

                padding: const EdgeInsets.symmetric(horizontal: 16),

                child: ClipOval(

                  child: Image.asset(

                    'images/avatar.png',

                    width: 80,

                  ),

                ),

              ),

              Text(

                'jonas',

                style: TextStyle(fontWeight: FontWeight.bold),

              )

            ],

          ),

        ),

        Expanded(

          child: ListView(

            children: <Widget>[

              ListTile(

                leading: const Icon(Icons.add),

                title: const Text('Add account'),

              ),

              ListTile(

                leading: const Icon(Icons.settings),

                title: const Text('Manage accounts'),

              )

            ],

          ),

        )

      ],

    ),

  ),

);

}

最后

由于篇幅限制,pdf文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

Flutter 基础篇(二十一,前端开发实训

Flutter 基础篇(二十一,前端开发实训