顶部TabLayout的实现

TabBar是作为AppBar的一部分存在。Flutter SDK中提供了两种实现顶部TabLayout的方法,两者效果是一样的,但第二种功能更为丰富。具体为 TabBar + TabBarView两个weight结合。
在这里插入图片描述
话不多说上代码:

方法一:DefaultTabController

使用 DefaultTabController作为最外层控制器,联调 TabBar + TabBarView,这种方式简单方便,但致命缺点是拿不到当前选中tab的index

class FirstPage extends StatefulWidget {
  FirstPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  State<StatefulWidget> createState() => _FirstPageState();
}

/// DefaultTabController (TabBar + TabBarView) 使用 (内部还是TabController实现)
class _FirstPageState extends State<FirstPage> {
  final List<Tab> myTabs = <Tab>[
    Tab(text: '全部订单'),
    Tab(text: '已完成'),
    Tab(text: '未完成')
  ];

  @override
  Widget build(BuildContext context) {
	// 1. 使用 DefaultTabController 作为外层控制器
    return DefaultTabController(
      length: myTabs.length,// 定义tab数量
      child: Scaffold(
        appBar: AppBar(
          title: Text('FirstPage'),
          
		  // 2. 使用 TabBar
          bottom: TabBar(
            tabs: myTabs // 定义TabWeight,若数量和定义不一致会报错
          ),
        ),
		
		// 3. 使用 TabBarView
        body: TabBarView(
            children: <Widget>[
        
              /// 全部订单
              Center(child: Text('全部订单')),
        
              /// 已完成订单
              Center(child: Text('已完成')),
        
              /// 未完成订单
              Center(child: Text('未完成'))
            ]),
      ),
    );
  }
}

效果如下:
在这里插入图片描述

方法二:TabController

实现SingleTickerProviderStateMixin,重写初始化和注销方法,利用控制器TabController管理和更多操作,其实第一种方法内部也是由TabController实现的。

// 1. 实现 SingleTickerProviderStateMixin 
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
  TabController _tabController;
  
  static const List<Tab> _homeTopTabList = <Tab>[
    Tab(text: '音乐', icon: Icon(Icons.music_note)),
    Tab(text: '体育', icon: Icon(Icons.directions_run)),
    Tab(text: '天气', icon: Icon(Icons.cloud_queue)),
    Tab(text: '科技', icon: Icon(Icons.toys))
  ];

  // 2. 初始化状态
  @override
  void initState() {
    super.initState();
    // TabController的滚动事件会触发一次监听, 点击事件会触发两次监听(一次是正常触发,一次是tab的动画触发)
    _tabController = TabController(length: _homeTopTabList.length, vsync: this);
    
    // 添加监听获取tab选中下标
    _tabController.addListener((){
      _currentTopTabIndex = _tabController.index;
    });
  }
  
  // 3. 注销状态
  @override
  void dispose() {
    _tabController.dispose();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
          
          // 4. 添加TabBar
          bottom: TabBar(
            tabs: _homeTopTabList,
            controller: _tabController
          ),
        ),

		// 5. 添加TabBarView
        body: TabBarView(
          controller: _tabController,
          children: <Widget>[
            _tabMusic(context),
            _tabSport(context),
            _tabSport(context),
            _tabSport(context)
          ],
        ),
       );
  }

关于TabController 的监听有个坑 踩坑TabBar之TabController.addListener

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐