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

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

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

经典的TabBar是这样的:

代码如下:

      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:

自定义它的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<CustomTabPage> with TickerProviderStateMixin{

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

  @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: <Widget>[
          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);
                  }
              )
          )
        ],
      ),
    );
  }

最终效果如第一张图所示

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值