Flutter之AppBar的部分定制

本篇已同步到 个人博客 ,欢迎常来。

代码 最终预览效果如下:

AppBar定制-min.gif

一、定制Title

目标:App导航栏title换成需要切换条(iOS中叫Segment)
1、flutter提供的AppBar的title属性就是wigdet,所有我们可以直接把title设置为tabbar;
2、需要相应的页面来进行联动,所以需要关联SingleTickerProviderStateMixin, 且把tabbar的controller 和 TabBarView的controller设置为同一个controller

final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
class MyHomePage extends StatefulWidget {
  final String title;

  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  TabController _controller;
  @override
  void initState() {
    super.initState();
    _controller = TabController(length: 3, vsync: this); //初始化方法
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        title: TabBar(
          controller: _controller,
          tabs: <Widget>[
            Tab(
              icon: Icon(Icons.directions_car),
            ),
            Tab(
              icon: Icon(Icons.directions_transit),
            ),
            Tab(
              icon: Icon(Icons.directions_bike),
            ),
          ],
        ),
      ),
      body: TabBarView(
        controller: _controller,
        children: <Widget>[
          HomePage(
            title: "设置11111",
          ),
          HomePage(
            title: "设置22222",
          ),
          HomePage(
            title: "设置33333",
          ),
        ],
      ),
    );
  }

HomePage代码

class HomePage extends StatelessWidget {
  final String title;
  final Widget child;

  HomePage({Key key, this.child, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      child: Center(
        child: Text(title),
      ),
    );
  }
}

二、侧滑抽屉效果

1、方法一:系统自带(局限性,图片不能更改)
仅仅设置Scaffold的drawer就好

drawer: _buildDrawer(context),

2、方法二:Builder

leading: Builder(
          builder: (context) => IconButton(
                icon: new Icon(Icons.settings),
                onPressed: () => Scaffold.of(context).openDrawer(),
              ),
        ),

3、方法三:GlobalKey<ScaffoldState>

// 1.步奏一
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,// 2、步奏二
      drawer: _buildDrawer(context),
      leading: IconButton(
          icon: Icon(Icons.account_box),
          onPressed: () {
            // 3、步奏三
            _scaffoldKey.currentState.openDrawer();
          },
        ),
       );
    }

4、方法四:改变源码(不推荐)

    /// 到AppBar源码,修改的部分code
    Widget leading = widget.leading;
    if (/*leading == null && */widget.automaticallyImplyLeading) {
      if (hasDrawer) {
        leading = IconButton(
          icon: /*const Icon(Icons.menu)*/ leading ?? Icon(Icons.home), // 如果leading指定了widget那么
          onPressed: _handleDrawerButton,
          tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
        );
      } else {
        if (canPop)
          leading = useCloseButton ? const CloseButton() : const BackButton();
      }
    }
    if (leading != null) {
      leading = ConstrainedBox(
        constraints: const BoxConstraints.tightFor(width: _kLeadingWidth),
        child: leading,
      );
    }

附录:代码汇总

Widget _buildDrawer(BuildContext context) {
    return Drawer(
      child: ListView(
        dragStartBehavior: DragStartBehavior.down,
        children: <Widget>[
          // 1. 简单的头部
          // const DrawerHeader(
          //   child: Center(
          //     child: Text('我是侧边栏'),
          //   ),
          // ),
          // 2.复杂的用户头部
          // UserAccountsDrawerHeader 不能用const来修饰
          UserAccountsDrawerHeader(
            accountEmail: Text(
              '13456@qq.com',
              style: TextStyle(color: Colors.black),
            ),
            accountName: Text(
              'HandsomeMen',
              style: TextStyle(color: Colors.black),
            ),
            currentAccountPicture: GestureDetector(
              onTap: () {
                print('current user');
              },
              child: CircleAvatar(
                backgroundImage: NetworkImage(
                    'http://m.360buyimg.com/pop/jfs/t25441/342/232745157/35324/69b79175/5b696c57N739592b8.jpg'),
              ),
            ),
            otherAccountsPictures: <Widget>[
              GestureDetector(
                onTap: () => print('点击了otherAccountsPictures 111111'),
                child: CircleAvatar(
                  backgroundImage: NetworkImage(
                      'https://pic.qqtn.com/up/2018-9/15367146917869444.jpg'),
                ),
              ),
              GestureDetector(
                onTap: () => print('点击了otherAccountsPictures 222222'),
                child: CircleAvatar(
                  backgroundImage: NetworkImage(
                      'http://www.gx8899.com/uploads/allimg/160902/3-160Z2104544.jpg'),
                ),
              ),
            ],
            decoration: BoxDecoration(
              //装饰器提供背景图片
              image: DecorationImage(
                  fit: BoxFit.fill,
                  //使用网络图片怎么有问题
                  image: NetworkImage(
                      'http://www.86ps.com/UpLoadFiles/jpg/2011-10/2011100912585215837.jpg')
                  // image: new ExactAssetImage('images/bg.jpg'),
                  ),
            ),
          ),

          const ListTile(
            leading: Icon(Icons.account_box),
            title: Text('选卡1'),
          ),
          Divider(),
          const ListTile(
            leading: Icon(Icons.account_box),
            title: Text('选卡1'),
          ),
          Divider(),
          const ListTile(
            leading: Icon(Icons.account_box),
            title: Text('选卡1'),
          ),
        ],
      ),
    );
  }