Flutter学习之旅 - AppBar、TabBar、TabBarView实现头部顶部滑动导航

文章介绍了如何在Flutter中自定义AppBar,包括设置顶部按钮图标、颜色,以及取消debug图标。同时,详细讲解了如何使用TabBarTabBarView实现顶部导航,以及通过PreferredSize组件改变TabBar导航样式。此外,还讨论了自定义KeepAliveWrapper来缓存页面,并展示了如何获取TabBar下的索引值以及销毁组件的方法。
摘要由CSDN通过智能技术生成

AppBar自定义顶部按钮图标、颜色

属性描述
leading在标题前面显示的一个控件,在首页通常显示应用的logo;在其他页面通常显示为返回按键
title标题,通常显示为当前页面的标题文字,可以放组件
actions通常使用IconButton来表示,可以放按钮组件
bottom通常放tabBar,标题下面显示一个Tab导航栏
backgroundColor导航栏背景颜色
iconTheme图标样式
centerTitle标题是否居中显示

取消debug图标

return MaterialApp(
  debugShowCheckedModeBanner: false ,//去掉debug图标
  home:Tabs(),
  ...
)

TabBar TabBarView来实现顶部导航

  1. 混入SingleTickerProviderStateMixin
class _HomePage extends State<HomePage> with SingleTickerProviderStateMixin{}
  1. 定义TabController
late TabController _tabController;


void initState() {
  //TODO: implement initState
  super.initState();
  _tabController = TabController(length: 3,vsync: this)
}

其实在Scaffold组件中还可以嵌套Scaffold,这里我们以home.dart为例子

//tabs.dart
class _TabsState extends State<Tabs>{
  int _currentIndex = 0;
  final List<Widget> _pages = const [
    HomePage(),
    MessagePage(),
    MyPage(),
  ];

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: null, //标题为null
      drawer: const Drawer(
        child: Text("左侧侧边栏"),
      ),
      body: _pages[_currentIndex], //修改
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: (index) {
          //index:点击索引值
          // print(index);
          setState(() {
            _currentIndex = index;
          });
        },
        items: const [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页"),
          BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),
          BottomNavigationBarItem(
              icon: Icon(Icons.my_library_add_outlined), label: "我的")
        ],
      ),
      floatingActionButton: Container(
        width: 60, //调整FloatingActionButton大小
        height: 60, //调整FloatingActionButton大小
        padding: const EdgeInsets.all(5),
        margin: const EdgeInsets.only(top: 10), //调整FloatingActionButton位置
        decoration: BoxDecoration(
            color: Colors.white, borderRadius: BorderRadius.circular(30)),
        child: FloatingActionButton(
          onPressed: () {},
          child: const Icon(Icons.add),
        ),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation
          .centerDocked, //floatingActionButtonLocation来调整floatingActionButton的位置
    );
  }
}
//home.dart(这里进行标头和顶部导航配置)
class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late TabController _tabController;
  
  void initState() {
    super.initState();
    _tabController = TabController(length: 3, vsync: this);//标头数量
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar( //一如既往的AppBar头
        leading: const CircleAvatar(
          backgroundImage: NetworkImage(
              "https://i2.hdslb.com/bfs/face/ce2494fac2fd854dd2813b8960521d8e0d1a527c.jpg@150w_150h.jpg"),
        ),
        bottom: TabBar( //标头
          controller: _tabController,
          tabs: const [
            Tab(child: Text("推荐")),
            Tab(child: Text("热门")),
            Tab(
              child: Text("动画"),
            )
          ],
        ),
      ),
      body: TabBarView(//这里配置相应标头所对应的页面
        controller: _tabController,
        children: const [Text("我的关注"), Text("我的热门"), Text("我的动漫")],
      ),
    );
  }
}

PreferredSize组件

PreferredSize可以改变appBar的高度

Scaffold(
  appBar:PreferredSize(//可以配置AppBar的高度
    preferredSize: Size.fromHeight(50),
    child: AppBar()
  ),
  body: Text()
)

改变TabBar导航样式

TabBar(
  isScrollable: true, //设置可以滚动
  indicatorColor: Colors.yellow, //底部指示器的颜色
  labelColor: Colors.green, //label选中颜色
  unselectedLabelColor: Colors.black, //label未选中的颜色
  indicatorSize: TabBarIndicatorSize.label, //修改指示长幅度,label:与字体同宽
  labelStyle: TextStyle(/*fontSize: number,...*/)
  controller: _tabController,
  tabs: ...
  body: ..
)

修改TabBar可以通过Container,但我们是通过以上的写法,TabBarbottom,所以我们不能使用Container(可以使用在title中)

自定义KeepAliveWrapper缓存页面

class KeepAliveWrapper extends StatefulWidget{
  ...
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}
class _KeepAliveWrapperState extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin{ //主要是AutomaticKeepAliveClientMixin
  
}
//KeepAliveWrapper.dart
import 'package:flutter/cupertino.dart';

class KeepAliveWrapper extends StatefulWidget {
  const KeepAliveWrapper(
      {super.key,  this.child, this.keepAlive = true});

  final Widget? child;
  final bool keepAlive;

  
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}

class _KeepAliveWrapperState extends State<KeepAliveWrapper>
    with AutomaticKeepAliveClientMixin {
  
  Widget build(BuildContext context) {
    return widget.child!; //可以通过widget拿到父组件的属性
  }

  
  bool get wantKeepAlive => widget.keepAlive; //默认缓存页面是因为我们自己设置的keepAlive本身为true
}

使用

TabBarView(
        controller: _tabController,
        children: [
          const Text("直播"),
          const TuiJianPage(),
          KeepAliveWrapper( //自定义缓存组件
              child: ListView(
            children: const [ListTile(title: Text("我是关注"))],
          )),
          const Text("我的动漫"),
          const Text("我的影视"),
          const Text("新征程"),
        ],
      ),

如何获取tab下的索引值

  1. 监听TabController下的事件
//记住,这个生命周期是初始化,所以要重启项目才生效
void initState() {
    super.initState();
    _tabController = TabController(length: 6, vsync: this);
    _tabController.addListener(() {
      //print(_tabController.index); //获取点击或滑动页面的索引值
      if (_tabController.animation!.value == _tabController.index) {
        print(_tabController.index);//获取点击或滑动页面的索引值
      }
    });
  }
  1. TabBar的onTap
TabBar(
            isScrollable: true, //设置可以滚动
            indicatorColor: Colors.red, //底部指示器的颜色
            labelColor: Colors.red, //label选中颜色
            unselectedLabelColor: Colors.black, //label未选中的颜色
            indicatorSize: TabBarIndicatorSize.label, //修改指示长幅度,label:与字体同宽
            controller: _tabController,
            tabs: const [
              Tab(child: Text("直播")),
              Tab(child: Text("推荐")),
              Tab(child: Text("热门")),
              Tab(child: Text("动画")),
              Tab(child: Text("影视")),
              Tab(child: Text("新征程")),
            ],
            onTap: (index) {
              //只能监听点击事件,没办法监听滑动
              print(index);
            },
          ),

销毁组件

//dispose:组件销毁的时候触发

void dispose() {
  super.dispose();
  //销毁_tabController
  _tabController.dispose(); 
}

这样的话我们的状态会丢失

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

结城明日奈是我老婆

支持一下一直热爱程序的菜鸟吧

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

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

打赏作者

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

抵扣说明:

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

余额充值