Flutter 76: 图解基本 TabBar 标签导航栏 (二)

简介: 0 基础学习 Flutter,第七十六步:自定义 ACETabBarIndicator 标签指示器!

      小菜刚刚学习了 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 案例源码


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

来源: 阿策小和尚

目录
相关文章
|
1月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
179 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
4月前
|
UED
Flutter&鸿蒙next 中的 Drawer 导航栏
在 Flutter 中,Drawer 是一个常用的侧边栏导航组件,通过点击菜单按钮或滑动屏幕显示。它用于展示导航项、用户信息和应用设置等。本文通过一个简单的示例代码,介绍了如何使用 Drawer 实现多页面导航,包括 Drawer 的基本结构、ListView 和 ListTile 的使用,以及页面内容的切换。希望对理解和使用 Flutter 的 Drawer 组件有所帮助。
162 1
|
7月前
|
开发者
Flutter笔记:Widgets Easier组件库 - 使用标签(Tag)
Flutter笔记:Widgets Easier组件库 - 使用标签(Tag)
185 0
|
8月前
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
flutter 导航组件 AppBar (含顶部选项卡TabBar,抽屉菜单 drawer ,自定义导航图标)
159 1
|
8月前
|
UED
Flutter-无限循环滚动标签
Flutter-无限循环滚动标签
140 0
|
8月前
Flutter 滚动距离来设置TabBar的位置,点击TabBar滚动的到指定的位置
Flutter 滚动距离来设置TabBar的位置,点击TabBar滚动的到指定的位置
|
Android开发 iOS开发
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
Flutter应用开发,系统样式改不了?SystemChrome 状态栏、导航栏、屏幕方向……想改就改
Flutter仿写微信导航栏快速实现页面导航
Flutter仿写微信导航栏快速实现页面导航
|
Dart 开发者
【Flutter】侧拉导航栏实现 ( Drawer 组件 | PageView 组件 )(二)
【Flutter】侧拉导航栏实现 ( Drawer 组件 | PageView 组件 )(二)
320 0
【Flutter】侧拉导航栏实现 ( Drawer 组件 | PageView 组件 )(二)
|
Dart 开发者
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)
395 0
【Flutter】底部导航栏实现 ( BottomNavigationBar 底部导航栏 | BottomNavigationBarItem 导航栏条目 | PageView )(二)

热门文章

最新文章

  • 1
    【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
    33
  • 2
    flutter3-wetrip跨平台自研仿携程app预约酒店系统模板
    34
  • 3
    通过外部链接启动 Flutter App(详细介绍及示例)
    33
  • 4
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    162
  • 5
    零基础构建即时通讯开源项目OpenIM移动端-Flutter篇
    102
  • 6
    flutter3-dart3-dymall原创仿抖音(直播+短视频+聊天)商城app系统模板
    64
  • 7
    【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    179
  • 8
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    56
  • 9
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
    82
  • 10
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    179