前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter跨平台移动端开发丨顶部导航栏 TabBar Widget

Flutter跨平台移动端开发丨顶部导航栏 TabBar Widget

作者头像
码脑
发布2019-07-08 18:08:15
1.8K0
发布2019-07-08 18:08:15
举报
文章被收录于专栏:大前端大前端

支持左右滑动切换、不限 item 数量的 tabbar 是分类信息列表展示必不可少的组件,在 flutter 中可通过 AppBar + TabBar + PageView + ListView 完成这个需求


TabBar 部件

支持修改 tab 背景颜色、底部横线颜色,tab 上的按钮样式以及对应切换的页面,可通过 List 传入,这样可以支持更多拓展需求

代码语言:javascript
复制
import 'package:delongzhixuan/main/tab/MainTab.dart';
import 'package:flutter/material.dart';

/**
 * @des 顶部 tab 部件
 * @author liyongli 20190704
 * */
class TabWidget extends StatefulWidget{

  // item 组件
  List<Widget> tabItems;

  // item 组件对应的 widget
  List<Widget> tabItemWidgets;

  // tab 的背景颜色
  Color backgroundColor;

  // item 底部横线颜色
  Color indicatorColor;

  // item 对应的 widget 控制器
  PageController pageController;

  TabWidget({
    @required this.tabItems,
    @required this.tabItemWidgets,
    this.backgroundColor,
    this.indicatorColor,
    this.pageController
  }):super();

  @override
  State<StatefulWidget> createState() => _TabWidgetState();

}

/**
 * @des 顶部 tab 部件 State
 * @author liyongli 20190704
 * */
class _TabWidgetState extends State<TabWidget> with SingleTickerProviderStateMixin{

  TabController tabController;

  @override
  void initState() {
    super.initState();
    tabController = new TabController(length: widget.tabItems.length, vsync: this);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(

        // 顶部 TabBar
        title: Text(MainTabState.pageNameList[1], style: MainTabState.appbarTestStyle),
        backgroundColor: MainTabState.appbarBackgroundColor,
        centerTitle: true,
        bottom: TabBar(
          isScrollable: true, // 设置是否支持左右滑动
          controller: tabController, // 控制器
          indicatorColor: widget.indicatorColor, // item 底部横线颜色
          tabs: widget.tabItems, // 设置列表内容
        ),
      ),

      // TabBar 对应的 widget
      body: new PageView(
        controller: widget.pageController,
        children: widget.tabItemWidgets,
        onPageChanged: (index){
          tabController.animateTo(index);
        },
      ),
    );
  }

  @override
  void dispose() {
    tabController.dispose();
    super.dispose();
  }
}

TabBar 部件 item 对应的页面

也就是 ListView 部分,修改 initPageWidget 返回的 widget 为你需要的样式即可

代码语言:javascript
复制
import 'package:flutter/material.dart';

/**
 * @des 顶部 tab 部件对应的 widget
 * @author liyongli 20190704
 * */
class TabItemWidget extends StatefulWidget {

  String itemIndex;

  TabItemWidget(this.itemIndex);

  @override
  State<StatefulWidget> createState() => _TabItemWidgetState();

}

/**
 * @des 顶部 tab 部件对应的 widget state
 * @author liyongli 20190704
 * */
class _TabItemWidgetState extends State<TabItemWidget> {

  @override
  Widget build(BuildContext context) {
    return initPageWidget();
  }

  /**
   * 初始化 page widget
   * */
  Widget initPageWidget(){
    return ListView.builder(itemBuilder: (context, i){
      return Container(
        alignment: Alignment.center,
        width: double.maxFinite,
        height: 100.0,
        decoration: BoxDecoration(
          border: Border(bottom: BorderSide(color: Color(0xff000000), width: 0.2))
        ),
        child: Text("${widget.itemIndex} - $i", style: TextStyle(color: Color(0xff000000), fontSize: 20.0),),
      );
    });
  }
}

TabBar 部件如何应用

代码语言:javascript
复制
import 'package:delongzhixuan/utils/tab/TabWidget.dart';
import 'package:delongzhixuan/utils/tab/TabItemWidget.dart';
import 'package:flutter/material.dart';

/**
 * @des 产品首页
 * @author liyongli 20190704
 * */
class MainProduct extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => _MainProductState();

}

/**
 * @des 产品首页 State
 * @author liyongli 20190704
 * */
class _MainProductState extends State<MainProduct> {

  // 控制器
  PageController pageController;

  // 模拟数据
  List<String> items = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10",];

  // tabbar 按钮集合
  List<Widget> tabItems = new List<Widget>();

  // tabbar 按钮对应的页面集合
  List<Widget> tabItemWidgets = new List<Widget>();

  @override
  void initState() {
    super.initState();
    pageController = new PageController();
    tabItems = _initTabItems(items, tabItems, false);
    tabItemWidgets = _initTabItemWidgets(items, tabItemWidgets);
    setState(() { });
  }

  @override
  Widget build(BuildContext context) {
    return _initPageWidget(context);
  }

  /**
   * 初始化 page widget
   * */
  Widget _initPageWidget(BuildContext context){
    return new TabWidget(
      tabItems: tabItems,
      tabItemWidgets: tabItemWidgets,
      pageController: pageController,
      indicatorColor: Colors.yellow,
    );
  }

  /**
   * 初始化 tab item 部件
   *
   * @params itemNameList 存储 tab item 名字的集合
   * @params itemWidgetList 转化完成后返回的集合
   * @params clear 是否需要在转化开始前,先行清空返回数组内的数据,主要用于应对分页加载刷新时的场景
   *
   * @return 已完成转化的 widget 集合
   * */
  List<Widget> _initTabItems(List<String> itemNameList, List<Widget> itemWidgetList, bool clear){

    // 检查传入的名字集合是否有数据,若没有数据则 return null
    if(null == itemNameList || itemNameList.length < 1){
      return null;
    }

    // 检查目标集合是否为空,为空则创建
    if(null == itemWidgetList){
      itemWidgetList = new List<Widget>();
    }

    // 检查是否需要先行清空 widget 集合数据
    if(clear && itemWidgetList.length > 0){
      itemWidgetList.clear();
    }

    // 开始转化
    for(var i = 0 ; i < itemNameList.length ; i++){
      itemWidgetList.add(
          new FlatButton(
              onPressed: (){pageController.jumpTo(MediaQuery.of(context).size.width * i);},
              child: Text(itemNameList[i], style: TextStyle(color: Color(0xffffffff)),)
          )
      );
    }

    return itemWidgetList;
  }

  /**
   * 初始化 tab item 对应的 widget(ListView 列表)
   *
   * @params itemNameList 存储 tab item 名字的集合
   * @params itemWidgetList 转化完成后返回的集合
   *
   * @return 已完成初始化的 tab item 对应的 widget 的数据集合
   * */
  List<Widget> _initTabItemWidgets(List<String> itemNameList, List<Widget> itemWidgetList){

    // 检查传入的名字集合是否有数据,若没有数据则 return null
    if(null == itemNameList || itemNameList.length < 1){
      return null;
    }

    // 检查目标集合是否为空,为空则创建
    if(null == itemWidgetList){
      itemWidgetList = new List<Widget>();
    }

    // 开始创建
    for(var i = 0 ; i < itemNameList.length ; i++){
      itemWidgetList.add(new TabItemWidget(itemNameList[i]));
    }

    return itemWidgetList;
  }

}

运行结果

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.07.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • TabBar 部件
  • TabBar 部件 item 对应的页面
  • TabBar 部件如何应用
  • 运行结果
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档