• 【Flutter】容器类组件之Scaffold、TabBar、底部导航


    前言

    一个完整的路由页可能会包含导航栏、抽屉菜单(Drawer)以及底部Tab导航菜单等。Flutter Material组件库提供了一些现成的组件来减少开发任务。Scaffold是一个路由页的骨架,使用它可以很容易地拼装出一个完整的页面。

    接口描述

    AppBar是一个Material风格的导航栏,通过它可以设置导航栏标题、导航栏菜单、导航栏底部的Tab标题等。

    AppBar({
        Key key,
        // 导航栏最左侧的widget,常见为抽屉菜单按钮或返回按钮。可手动来设置这一项
        this.leading,
        // 如果leading为null,是否自动实现默认的leading按钮
        this.automaticallyImplyLeading = true,
        // 页面标题
        this.title,
        // 导航栏右侧菜单
        this.actions,
        this.flexibleSpace,
        // 导航栏底部菜单,通常为Tab按钮组
        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,
      }) : assert(automaticallyImplyLeading != null),
           assert(elevation == null || elevation >= 0.0),
           assert(primary != null),
           assert(titleSpacing != null),
           assert(toolbarOpacity != null),
           assert(bottomOpacity != null),
           preferredSize = Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
           super(key: key);
    
    

    Material组件库中提供了一个TabBar组件,它可以快速生成Tab菜单。

    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,
      }) : assert(tabs != null),
           assert(isScrollable != null),
           assert(dragStartBehavior != null),
           assert(indicator != null || (indicatorWeight != null && indicatorWeight > 0.0)),
           assert(indicator != null || (indicatorPadding != null)),
           super(key: key);
    
    

    Material库提供了一个TabBarView组件,通过它不仅可以轻松的实现Tab页,而且可以非常容易的配合TabBar来实现同步切换和滑动状态同步.

    const TabBarView({
        Key key,
        @required this.children,
        this.controller,
        this.physics,
        this.dragStartBehavior = DragStartBehavior.start,
      }) : assert(children != null),
           assert(dragStartBehavior != null),
           super(key: key);
    
    

    无论是点击导航栏Tab菜单还是在页面上左右滑动,Tab页面都会切换,并且Tab菜单的状态和Tab页面始终保持同步!那它们是如何实现同步的呢?因为TabBar和TabBarView的controller是同一个!正是如此,TabBar和TabBarView正是通过同一个controller来实现菜单切换和滑动状态同步的。

    代码示例

    // Scaffold、TabBar、底部导航
    
    import 'package:flutter/material.dart';
    
    class ScaffoldTest extends StatefulWidget {
      @override
      _ScaffoldTestState createState() => _ScaffoldTestState();
    }
    
    class _ScaffoldTestState extends State<ScaffoldTest> with SingleTickerProviderStateMixin{
      int _selectedIndex = 2;
      TabController _tabController;
      List tabs = ['会话', '系统'];
    
      @override
      void initState() {
        print('初始化了数据!');
        super.initState();
        // 创建Controller
        _tabController = TabController(length: tabs.length, vsync: this);
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          // AppBar是一个Material风格的导航栏,通过它可以设置导航栏标题、导航栏菜单、导航栏底部的Tab标题等
          appBar: AppBar(
    
            // 导航栏最左侧的widget
            leading: Builder(builder: (context) {
              return IconButton(
                // 自定义图标
                icon: Icon(Icons.dashboard, color: Colors.red,),
                onPressed: () {
                  // 打开抽屉菜单
                  Scaffold.of(context).openDrawer();
                },
              );
            }),
    
            // 导航栏标题
            title: Text('Test App'),
    
            // 导航栏右侧菜单
            actions: <Widget>[
              IconButton(icon: Icon(Icons.share),onPressed: () {},),
            ],
    
            // Tab菜单
            bottom: TabBar(
              controller: this._tabController,
    //          isScrollable: true,
              tabs: <Widget>[
                Tab(text: tabs[0]),
                Tab(text: tabs[1]),
              ],
            ),
    
          ),
    
          // 抽屉
          drawer: MyDrawer(),
    
          body: TabBarView(
            controller: this._tabController,
            children: <Widget>[
              Container(
                alignment: Alignment.center,
                  child: Text(tabs[0], textScaleFactor: 10),
              ),
              Container(
                alignment: Alignment.center,
                child: Text(tabs[1], textScaleFactor: 10),
              ),
            ],
          ),
    
          // 底部导航
          bottomNavigationBar: BottomNavigationBar(
            items: <BottomNavigationBarItem>[
              BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页'), backgroundColor: Colors.blue,),
              BottomNavigationBarItem(icon: Icon(Icons.system_update_alt), title: Text('数据'), backgroundColor: Colors.blue,),
              BottomNavigationBarItem(icon: Icon(Icons.notifications_active), title: Text('通知'), backgroundColor: Colors.blue,),
              BottomNavigationBarItem(icon: Icon(Icons.settings), title: Text('设置'), backgroundColor: Colors.blue,),
            ],
            currentIndex: _selectedIndex,
            fixedColor: Colors.red,
            onTap: _onItemTapped,
          ),
    
          // 悬浮按钮
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: _onAdd,
            backgroundColor: Colors.blue,
          ),
          // 设置悬浮按钮的位置为底部导航栏的正中间
    //      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    
          // 增加打洞按钮
    //      bottomNavigationBar: BottomAppBar(
    //        color: Colors.green,
    //        // 底部导航栏打一个圆形的洞
    //        shape: CircularNotchedRectangle(),
    //        child: Row(
    //          children: <Widget>[
    //            IconButton(icon: Icon(Icons.home),),
    //            // 中间位置空出
    //            SizedBox(),
    //            IconButton(icon: Icon(Icons.business),),
    //          ],
    //          mainAxisAlignment: MainAxisAlignment.spaceAround,
    //        ),
    //      ),
    
        );
      }
    
      void _onItemTapped(int index) {
        setState(() {
          _selectedIndex = index;
        });
      }
    
      void _onAdd() {
        print('_onAdd');
      }
    
    }
    
    
    class MyDrawer extends StatelessWidget {
    
      MyDrawer({Key key,}) : super(key:key);
    
      @override
      Widget build(BuildContext context) {
        return Drawer(
          child: MediaQuery.removePadding(
              context: context, 
              // 移除抽屉菜单顶部默认留白
              removeTop: true,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
    
                  Padding(
                    padding: const EdgeInsets.only(top: 38.0),
                    child: Row(
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 16.0),
                          child: ClipOval(
                            child: Image.asset('assets/images/avatar.png',  80,),
                          ),
                        ),
                        Text('parzulpan',style: TextStyle(fontWeight: FontWeight.bold),)
                      ],
                    ),
                  ),
    
                  Expanded(
                    child: ListView(
                      children: <Widget>[
                        ListTile(
                          leading: const Icon(Icons.add),
                          title: const Text('增加账户'),
                        ),
                        ListTile(
                          leading: const Icon(Icons.info),
                          title: const Text('账户管理'),
                        ),
    
                      ],
                    ),
                  )
                ],
              )
          ),
        );
      }
    
    }
    
    

    总结

    暂无

  • 相关阅读:
    MySql中的变量定义
    mysql常用脚本
    Spring中依赖注入的使用和配置
    在linux下通过sh运行java程序
    linux下shell脚本学习
    eclipse导出jar包
    mysql中游标的使用
    netty中LengthFieldBasedFrameDecoder的使用
    网络游戏服务器架构(转)
    H2 database的使用
  • 原文地址:https://www.cnblogs.com/parzulpan/p/12123325.html
Copyright © 2020-2023  润新知