flutter系列之自定义TabBar与PageView联动

发布时间:2024-12-18 08:01

TabBar + PageView可以说是flutter开发中的经典组合,所以flutter为开发者提供了非常轻松便捷的方式就可以实现TabBar和PageView的联动效果。

flutter系列之自定义TabBar与PageView联动_第1张图片

原生开发TabBar + PageView还是比较麻烦的,但是flutter几行代码就可以搞定,而且还自带动画效果,还提供了很高的自定义方式。

经典的TabBar是这样的:

flutter系列之自定义TabBar与PageView联动_第2张图片

代码如下:

      TabBar(
              labelColor: Colors.blue,
              labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
              unselectedLabelColor: Colors.black54,
              unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
              isScrollable: true,
              controller: _tabController,
              onTap: _changeTab,
              tabs: _titleList.map((e) => Tab(text: e)).toList(),
            )

我们可以自定义成这样子的TabBar:

flutter系列之自定义TabBar与PageView联动_第3张图片

自定义它的indicator,你可以写成你想要的任何样式,代码如下:

       TabBar(
              labelColor: Colors.blue,//选中的颜色
              labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
              unselectedLabelColor: Colors.black54,//未选中的颜色
              unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
              isScrollable: true,
              //自定义indicator样式
              indicator: BoxDecoration(
                  color: Colors.amber,
                  borderRadius: BorderRadius.all(Radius.circular(15))
              ),
              controller: _tabController,
              onTap: _changeTab,
              tabs: _titleList.map((e) => Tab(text: e)).toList(),
            )

这个indicator需要一个decoration,所以我们传入一个BoxDecoration就可以自定义indicator。

接下来就是和PageView的联动,和PageView联动,需要两个controller,一个是控制tab移动的TabController,一个是控制PageView滑动的PageController

class _CustomTabPageState extends State with TickerProviderStateMixin{

  TabController _tabController;
  PageController _pageController;
  List _titleList = ['关注','推荐', '抗疫', '热榜', '精品课', '旅游'];

  @override
  void initState() {
    super.initState();
    _tabController = TabController(vsync: this, length: _titleList.length);
    _pageController = PageController();
  }

  void _changeTab(int index) {
    _pageController.animateToPage(index, duration: Duration(milliseconds: 300), curve: Curves.ease);
  }

  void _onPageChanged(int index) {
    _tabController.animateTo(index, duration: Duration(milliseconds: 300));
  }

  @override
  void dispose() {
    _pageController.dispose();
    _tabController.dispose();
    super.dispose();
  }
}

首先state需要混入一个TickerProviderStateMixin,这样才可以在构建TabController的时候,vsync参数传入this,这个是因为做动画的需要,具体的说明可以查看基础教程。

然后我们定义两个监听函数,分别监听tab滚动时,调用PageController使页面跟着tab滑动,另外一个监听函数是监听页面滑动时,通过TabController控制tab的移动,最后别忘记在dispose的时候释放这两个controller。

build方法的代码如下

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('自定义TabBar', style: TextStyle(color: Colors.black54),),
        backgroundColor: Colors.white,
        brightness: Brightness.light,
        elevation: 0,
        iconTheme: IconThemeData(
            color: Colors.black54
        ),
      ),
      body: Column(
        children: [
          Container(
            width: double.infinity,
            color: Colors.white,
            padding: EdgeInsets.symmetric(vertical: 10, horizontal: 5),
            height: 45,
            child: TabBar(
              labelColor: Colors.blue,//选中的颜色
              labelStyle: TextStyle(color: Colors.blue, fontSize: 14),
              unselectedLabelColor: Colors.black54,//未选中的颜色
              unselectedLabelStyle: TextStyle(color: Colors.black54, fontSize: 14),
              isScrollable: true,
              //自定义indicator样式
              indicator: BoxDecoration(
                  color: Colors.amber,
                  borderRadius: BorderRadius.all(Radius.circular(15))
              ),
              controller: _tabController,
              onTap: _changeTab,
              tabs: _titleList.map((e) => Tab(text: e)).toList(),
            ),
          ),
          Expanded(
              child: PageView.builder(
                  physics: BouncingScrollPhysics(),
                  controller: _pageController,
                  onPageChanged: _onPageChanged,
                  itemCount: _titleList.length,
                  itemBuilder: (context, index) {
                    return PageItemView(index);
                  }
              )
          )
        ],
      ),
    );
  }

最终效果如第一张图所示

 

 

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号