Futter基础11篇: 实现自定义AppBar 定义顶部Tab切换、底部Tab结合顶部Tab实现类似头条页面布局

效果图:

Home.dart
在这里插入图片描述
AppBarDemo.dart
在这里插入图片描述
Categroy.dart
在这里插入图片描述

底部导航基本架构参考:flutter实现底部导航

main.dart

import 'package:flutter/material.dart';

import 'routes/Routes.dart';

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

class MyApp extends StatelessWidget{

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      debugShowCheckedModeBanner: false,      //去掉debug图标

      initialRoute: '/',  //初始化的时候加载的路由
//        home: Tabs(),      //将代码全部抽离出去成一个Tabs组件,再抽离成一个初始化路由组件,在上方       initialRoute: '/',
        //配置命名路由
        onGenerateRoute: oonGenerateRoute //将抽离出去的路由传值规范赋值给左边,而不是执行,记住喔!
    );
  }
}

Routes.dart

import '../pages/Tabs.dart';

import 'package:flutter/material.dart';

import '../pages/AppBarDemo.dart';

//配置路由
final  routes={                   //配置命名路由
  '/':(context)=>Tabs(),  //命名路由传值 arguments工具是必须的
  '/appBarDemo':(context)=>AppBarDemoPage()
};

//固定写法
var oonGenerateRoute=(RouteSettings settings) {
  // 统一处理
  final String name = settings.name;    //得到命名路由的名字,例如:'/form'
  final Function pageContentBuilder = routes[name];  //得到命名路由的键去获取值,例如:(context)=>FormPage(),
  if (pageContentBuilder != null) {
    if (settings.arguments != null) {
      final Route route = MaterialPageRoute(
          builder: (context) => pageContentBuilder(context, arguments: settings.arguments));
      return route;
    } else {
      final Route route = MaterialPageRoute(
          builder: (context) => pageContentBuilder(context));
      return route;
    }
  }
};

Tabs.dart

import 'package:flutter/material.dart';
import 'tabs/Category.dart';
import 'tabs/Home.dart';
import 'tabs/Setting.dart';

class Tabs extends StatefulWidget {
  final index;    //用来作为返回根路由时,判断要显示第几个底部导航项的坐标

Tabs({Key key,this.index=0}) : super(key: key);   //可选参数,默认是0

  @override
  _TabsState createState() => _TabsState(this.index); //把当前坐标通过_TabsState构造方法传给_TabsState类
}

class _TabsState extends State<Tabs> {
  int _currentIndex;
  _TabsState(index){    //接收Tabs 类调用时,传过来的参数,赋值给 _currentIndex
    this._currentIndex=index;
  }

  List _pageList = [    //先将所有页面放到List集合内
    HomePage(),
    CategoryPage(),
    SettingPage()
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FlutterDemo'),
      ),
      body: this._pageList[this._currentIndex],   //再根据下标获取对应页面设置到body 里
      bottomNavigationBar: BottomNavigationBar(     //自定义底部导航条

          currentIndex: this._currentIndex,   //配置对应的索引值选中
          onTap: (int index){
            setState(() {     //改变状态
              this._currentIndex=index;      //更改选中的Tab坐标
            });
          },
//          iconSize: 45.0,   //Icon的大小,默认在20左右
          fixedColor: Colors.red, //选中的颜色,默认是蓝色
          items:[
            BottomNavigationBarItem(      //设置导航项
                icon:Icon(Icons.home),
                title: Text('首页')
            ),
            BottomNavigationBarItem(      //设置导航项
                icon:Icon(Icons.category),
                title: Text('分类')
            ),
            BottomNavigationBarItem(      //设置导航项
                icon:Icon(Icons.settings),
                title: Text('设置')
            )
          ]
      ),
    );
  }
}

AppBarDemo.dart

import 'package:flutter/material.dart';

class AppBarDemoPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(      //顶部导航切换
      length: 2,    //必须配置:顶部图标一共多少个

      child: Scaffold(
        appBar: AppBar(
          title: Text('AppBarDemoPage'),
          backgroundColor: Colors.red,    //设置导航上的背景颜色
          centerTitle: true,      //设置:无论是在Android 还是 ios 上,标题都是居中显示
//        leading: Icon(Icons.menu),    //给导航左边添加图标,默认是返回图标,无法监听
//        leading: IconButton(
//          icon: Icon(Icons.menu),   //给导航左边添加图标,默认是返回图标,可以监听
//          onPressed: (){
//            print('menu');
//          },
//        ),
//          actions: <Widget>[          //右侧添加图标按钮
//            IconButton(
//              icon: Icon(Icons.search),
//              onPressed: (){
//                print('search');
//              },
//            ),
//            IconButton(                //右侧添加第二个图标按钮
//              icon: Icon(Icons.settings),
//              onPressed: (){
//                print('settings');
//              },
//            )
//          ],
        bottom: TabBar(
          tabs: <Widget>[         //配置Tabs菜单,系统会根据这里配置的是顺序对应下边body:TabBarView 里元素的顺序进行显示
            Tab(text: '热门',),
            Tab(text: '推荐',)
          ],
        ),
        ),
        body: TabBarView(
          children: <Widget>[
           ListView(
             children: <Widget>[
               ListTile(
                 title: Text('第一个tab'),
               ),
               ListTile(
                 title: Text('第一个tab'),
               ),
               ListTile(
                 title: Text('第一个tab'),
               )
             ],
           ),
            ListView(
              children: <Widget>[
                ListTile(
                  title: Text('第二个tab'),
                ),
                ListTile(
                  title: Text('第二个tab'),
                ),
                ListTile(
                  title: Text('第二个tab'),
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}

Home.dart

import 'package:flutter/material.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          RaisedButton(
            child: Text('跳转到appBar'),
            onPressed: (){
              //路由跳转
              Navigator.pushNamed(context, '/appBarDemo');
            },
          )
        ],
      ),
    );
  }
}

Categroy.dart

import 'package:flutter/material.dart';

class CategoryPage extends StatefulWidget {
  @override
  _CategoryPageState createState() => _CategoryPageState();
}

class _CategoryPageState extends State<CategoryPage> {
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 4,
      child: Scaffold(      //在Scaffold 里再嵌套Scaffold
        appBar: AppBar(
          backgroundColor: Colors.black26,

          /**
           *  将顶部导航写在title里是为了防止,当Scaffold嵌套Scaffold时,发生两个顶部的bug,为了修复这个bug,
           *  我们就可以把顶部导航条写在title里
           */
        title: Row(
            children: <Widget>[
              Expanded(
                child: TabBar(
                  indicatorColor: Colors.blue,   //设置指示器的颜色
                  labelColor: Colors.blue,   //设置:选中颜色
                  unselectedLabelColor: Colors.white, //设置:未选中颜色
                  indicatorSize: TabBarIndicatorSize.label,   //选中时,底部指示条与文字一样长,默认是tab

                  tabs: <Widget>[
                    Tab(text: '热销'),
                    Tab(text: '推荐',),
                    Tab(text: '三',),
                    Tab(text: '四',)
                  ],
                ),
              )
            ],
          ),
        ),
        body: TabBarView(
          children: <Widget>[
            ListView(
              children: <Widget>[
                ListTile(
                  title: Text('第一个tab'),
                ),
                ListTile(
                  title: Text('第一个tab'),
                ),
                ListTile(
                  title: Text('第一个tab'),
                )
              ],
            ),
            ListView(
              children: <Widget>[
                ListTile(
                  title: Text('第二个tab'),
                ),
                ListTile(
                  title: Text('第二个tab'),
                ),
                ListTile(
                  title: Text('第二个tab'),
                )
              ],
            ),
            ListView(
              children: <Widget>[
                ListTile(
                  title: Text('第三个tab'),
                ),
                ListTile(
                  title: Text('第三个tab'),
                ),
                ListTile(
                  title: Text('第三个tab'),
                )
              ],
            ),
            ListView(
              children: <Widget>[
                ListTile(
                  title: Text('第四个tab'),
                ),
                ListTile(
                  title: Text('第四个tab'),
                ),
                ListTile(
                  title: Text('第四个tab'),
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}

Demo目录结构:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王睿丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值