当前位置:   article > 正文

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

flutter头部滑动标签

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

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

取消debug图标

return MaterialApp(
  debugShowCheckedModeBanner: false ,//去掉debug图标
  home:Tabs(),
  ...
)
  • 1
  • 2
  • 3
  • 4
  • 5

TabBar TabBarView来实现顶部导航

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


void initState() {
  //TODO: implement initState
  super.initState();
  _tabController = TabController(length: 3,vsync: this)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

其实在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的位置
    );
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
//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("我的动漫")],
      ),
    );
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

PreferredSize组件

PreferredSize可以改变appBar的高度

Scaffold(
  appBar:PreferredSize(//可以配置AppBar的高度
    preferredSize: Size.fromHeight(50),
    child: AppBar()
  ),
  body: Text()
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

改变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: ..
)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

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

自定义KeepAliveWrapper缓存页面

class KeepAliveWrapper extends StatefulWidget{
  ...
  State<KeepAliveWrapper> createState() => _KeepAliveWrapperState();
}
class _KeepAliveWrapperState extends State<KeepAliveWrapper> with AutomaticKeepAliveClientMixin{ //主要是AutomaticKeepAliveClientMixin
  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
//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
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

使用

TabBarView(
        controller: _tabController,
        children: [
          const Text("直播"),
          const TuiJianPage(),
          KeepAliveWrapper( //自定义缓存组件
              child: ListView(
            children: const [ListTile(title: Text("我是关注"))],
          )),
          const Text("我的动漫"),
          const Text("我的影视"),
          const Text("新征程"),
        ],
      ),
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

如何获取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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  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);
            },
          ),
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

销毁组件

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

void dispose() {
  super.dispose();
  //销毁_tabController
  _tabController.dispose(); 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/431831
推荐阅读
相关标签
  

闽ICP备14008679号