flutter自定义tabbar

4,171 阅读1分钟

自定义tabbar主要是修改滑动条的样式,字体和颜色根据需求自己改

原始的tabbar样式

tabbar_0.gif

样式一

tabbar_2.gif

这个不需要修改原始的Tabbar代码,只需要修改indicator的样式

TabBar(
  tabs: tabList,
  indicatorColor: Colors.white,
  indicatorWeight: 0,
  indicator: BoxDecoration(
      color: Colors.white,
      borderRadius: BorderRadius.circular(45.sp),
      border: Border.all(width: 10.sp,color: GsColors.gray10)
  ),
  labelColor: GsColors.blue,
  unselectedLabelColor: GsColors.black,
  labelStyle: TextStyle(
    color: Colors.blue,
    fontWeight: FontWeight.bold,
    fontSize: GsFontSize.sp_36,
  ),
  unselectedLabelStyle: TextStyle(
    fontSize: GsFontSize.sp_36,
    // fontWeight: FontWeight.bold,
  ),
)

样式二

tabbar_1.gif

由于这个indicator的长和宽都是固定的,通过上面的方式无法修改,这时候需要深入Tabbar的源码去自定义效果。 下面是使用自定义类名后的tabbar,将Tabar类名改成CustomTabBarWidget,文件中相关的都要改类名

Container(
  width: ScreenUtil().screenWidth,
  color: bgColor ?? Colors.white,
  alignment: Alignment.centerLeft,
  child: SingleChildScrollView(
    scrollDirection: Axis.horizontal,
    child: CustomTabBarWidget(
      height: height ?? 130.sp,
      isScrollable: true,
      labelColor: selectLabelColor ?? GsColors.black,
      unselectedLabelColor: unselectLabelColor ?? Color(0xff666666),
      labelStyle: TextStyle(fontSize: 46.sp, fontWeight: GsFontWeight.medium),
      unselectedLabelStyle: TextStyle(fontSize: 44.sp, fontWeight: GsFontWeight.regular),
      indicatorWeight: 12.sp,
      indicatorColor: indicatorColor ?? GsColors.blueMain,
      indicatorSize: TabBarIndicatorSize.label,
      tabs: tabList,
    ),
  ),
)

将flutter的Tabbar拷贝一份,然后修改Tabbar类名,找到indicator的paint方法,在里面修改indicator的size。原代码中的indicator的size是根据tabbar的item的size去改变的

原代码:

if (indicatorSize == TabBarIndicatorSize.label) {
  final double tabWidth = tabKeys[tabIndex].currentContext!.size!.width;
  final double delta = ((tabRight - tabLeft) - tabWidth) / 2.0;
  tabLeft += delta;
  tabRight -= delta;
}

final EdgeInsets insets = indicatorPadding.resolve(_currentTextDirection);
final Rect rect = Rect.fromLTWH(tabLeft, 0.0, tabRight - tabLeft, tabBarSize.height);

修改后代码:

///滑动条的宽和高
double indicatorWidth = 58.sp;
double indicatorHeight = 12.sp;

if (indicatorSize == TabBarIndicatorSize.label) {
  final double tabWidth = tabKeys[tabIndex].currentContext.size.width;
  final double delta = ((tabRight - tabLeft - indicatorWidth)) / 2.0;
  tabLeft += delta;
  tabRight -= delta;
}
final EdgeInsets insets = indicatorPadding.resolve(_currentTextDirection);
final Rect rect = Rect.fromLTWH(tabLeft, tabBarSize.height - indicatorHeight, indicatorWidth, indicatorHeight);

tab切换抖动主要是切换的字体不一样导致的 1、通过设置tab字体的大小一样可以避免 2、代码修改(这种切换过程即将完成才会改变大小)

///滑动的抖动
///这里是切换的动画值
// return (controllerValue - index.toDouble()).abs().clamp(0.0, 1.0);
///取四舍五入,取消中间过度
return (controllerValue - index.toDouble()).abs().clamp(0.0, 1.0).roundToDouble();
void _handleTap(int index) {
  assert(index >= 0 && index < widget.tabs.length);
  ///点击切换的抖动
  ///_controller.index = index;或者_controller改小一点
  _controller.animateTo(index, _controller: Duration(milliseconds: 80));
  widget.onTap?.call(index);
}
```
```


代码地址:https://github.com/justyouzxy/flutter_demo/tree/main/lib/widgets/tabbar