前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Flutter 专题】76 图解基本 TabBar 标签导航栏 (二)

【Flutter 专题】76 图解基本 TabBar 标签导航栏 (二)

作者头像
阿策小和尚
发布2020-02-20 13:53:43
1.6K0
发布2020-02-20 13:53:43
举报
文章被收录于专栏:阿策小和尚阿策小和尚

和尚刚刚学习了 TabBar 标签导航栏的使用,其中对于标签指示器 indicator 的使用较少;和尚今天尝试一下自定义标签指示器;

TabBar 提供了 indicator 指示器属性;允许用户自定义 indicator,但自定义的指示器会导致 indicatorColor / indicatorWeight / indicatorPadding 属性失效;默认的指示器是 UnderlineTabIndicator

Decoration get _indicator {
  if (widget.indicator != null) return widget.indicator;
  final TabBarTheme tabBarTheme = TabBarTheme.of(context);
  if (tabBarTheme.indicator != null) return tabBarTheme.indicator;

  Color color = widget.indicatorColor ?? Theme.of(context).indicatorColor;
  if (color.value == Material.of(context).color?.value) color = Colors.white;

  return UnderlineTabIndicator(
      insets: widget.indicatorPadding,
      borderSide: BorderSide(width: widget.indicatorWeight, color: color));
}

源码分析

class ACETabBarIndicator extends Decoration {
  @override
  BoxPainter createBoxPainter([onChanged]) => _ACETabBarIndicatorPainter(this, onChanged);
}

class _ACETabBarIndicatorPainter extends BoxPainter {
  final ACETabBarIndicator decoration;
  _ACETabBarIndicatorPainter(this.decoration, VoidCallback onChanged);

  @override
  void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
    // TODO: implement paint
  }
}

分析源码可知,自定义 indicator 指示器均需继承自 Decoration;其中绘制 BoxPainter 时可以通过 OffsetImageConfiguration 获取对应 Tab 尺寸和所在位置;

案例尝试

和尚将自定义 ACETabBarIndicator 单独出来,并未自定义 TabBar,因此不能直接使用 TabBar 中属性,若需要直接使用 TabBar 中属性可以尝试将 ACETabBarIndicator 放置在 TabBar 源码中进行自定义;

自定义主要是实现各种样式的 paint 绘制过程,和尚简单尝试了如下几种指示器样式;

1. ACETabBarIndicatorType.circle -> 实心圆点

和尚以设置 height 为直径,在 Tab 底部中间位置绘制一个圆形,注意起始位置为底部中心位置减半径;

canvas.drawCircle(
    Offset(offset.dx + (configuration.size.width) / 2, configuration.size.height - _height),
    _height, _paint);
2. ACETabBarIndicatorType.triangle -> 上三角

和尚通过绘制 Path 来生成一个上三角;其中需要兼容一个三角高度上限;

if (_height > configuration.size.height) 
  _height = _kIndicatorHeight;
Path _path = Path()
  ..moveTo(offset.dx + (configuration.size.width) / 2 - _height, configuration.size.height)
  ..lineTo(_height * tan(pi / 6) + offset.dx + (configuration.size.width - _height) / 2,
      configuration.size.height - _height)
  ..lineTo(_height * tan(pi / 6) + offset.dx + (configuration.size.width + _height) / 2,
      configuration.size.height);
canvas.drawPath(_path, _paint);
3. ACETabBarIndicatorType.rrect -> 圆角矩形(整个 Tab)

和尚绘制一个圆角矩形,其中矩形的起始位置为 Offset 对应的 Tab 大小为 ImageConfiguration 尺寸;

canvas.drawRRect(
    RRect.fromRectAndRadius(
        Rect.fromLTWH(offset.dx, offset.dy, configuration.size.width, configuration.size.height),
        Radius.circular(_kIndicatorAngle)),
    _paint);
4. ACETabBarIndicatorType.rrect_inner -> 圆角矩形(有内边距)

和尚无法准确获取 TabWidgets 位置与尺寸,因此通过 height 来进行处理;其中矩形的起始高度需要减 1,因为 Paint 默认线宽为 1

canvas.drawRRect(
    RRect.fromRectAndRadius(
        Rect.fromLTWH(
            offset.dx + height, height - 1,
            configuration.size.width - height * 2,
            configuration.size.height - height * 2 - 2),
        Radius.circular(_kIndicatorAngle)),
    _paint);
5. ACETabBarIndicatorType.runderline -> 圆角下划线

TabBar 默认的指示器样式为 UnderlineTabIndicator;只需调整 Paint 笔触线样式为 round 即可;

canvas.drawLine(
    Offset(offset.dx, configuration.size.height - height / 2),
    Offset(offset.dx + configuration.size.width, configuration.size.height - height / 2),
    _paint..strokeWidth = height / 2);
6. ACETabBarIndicatorType.runderline_fixed -> 定长圆角下划线

和尚设置定长的下划线,需要注意的是若 Tab 宽度小于设置的 width 时,兼容默认的宽度;

if (_width > configuration.size.width)
  _width = configuration.size.width / 3;
canvas.drawLine(
    Offset(offset.dx + (configuration.size.width - _width) / 2, configuration.size.height - height / 2),
    Offset(offset.dx + (configuration.size.width + _width) / 2, configuration.size.height - height / 2),
    _paint..strokeWidth = height / 2);

ACETabBarIndicator 案例源码


和尚对自定义标签指示器的适配测试还不够完全,如有错误请多多指导!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 阿策小和尚 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 源码分析
  • 案例尝试
    • 1. ACETabBarIndicatorType.circle -> 实心圆点
      • 2. ACETabBarIndicatorType.triangle -> 上三角
        • 3. ACETabBarIndicatorType.rrect -> 圆角矩形(整个 Tab)
          • 4. ACETabBarIndicatorType.rrect_inner -> 圆角矩形(有内边距)
            • 5. ACETabBarIndicatorType.runderline -> 圆角下划线
              • 6. ACETabBarIndicatorType.runderline_fixed -> 定长圆角下划线
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档