You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中实现这种带连线的点式TabBar布局?

实现带连线的点式TabBar布局

一、自定义实现方案

你可以通过Row结合基础组件手动构建这种布局,完全掌控样式细节,核心思路如下:

  • 用Row横向排列所有点与连线
  • 区分选中/未选中状态的点样式(大小、颜色)
  • 连线部分用Container实现基础样式,需要动画时可替换为AnimatedContainer或CustomPaint

示例代码

class DottedTabBar extends StatefulWidget {
  final int itemCount;
  final int currentIndex;
  final ValueChanged<int> onTap;
  final Color selectedColor;
  final Color unselectedColor;

  const DottedTabBar({
    super.key,
    required this.itemCount,
    required this.currentIndex,
    required this.onTap,
    this.selectedColor = Colors.blue,
    this.unselectedColor = Colors.grey,
  });

  @override
  State<DottedTabBar> createState() => _DottedTabBarState();
}

class _DottedTabBarState extends State<DottedTabBar> {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(widget.itemCount, (index) {
        return Expanded(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              GestureDetector(
                onTap: () => widget.onTap(index),
                child: Container(
                  width: index == widget.currentIndex ? 20 : 12,
                  height: index == widget.currentIndex ? 20 : 12,
                  decoration: BoxDecoration(
                    color: index == widget.currentIndex
                        ? widget.selectedColor
                        : widget.unselectedColor,
                    shape: BoxShape.circle,
                  ),
                ),
              ),
              // 最后一个点不显示右侧连线
              if (index != widget.itemCount - 1)
                Expanded(
                  child: Container(
                    height: 2,
                    color: index < widget.currentIndex
                        ? widget.selectedColor
                        : widget.unselectedColor,
                  ),
                ),
            ],
          ),
        );
      }),
    );
  }
}

使用方式

int _selectedIndex = 0;

// 在build方法中调用
DottedTabBar(
  itemCount: 4,
  currentIndex: _selectedIndex,
  onTap: (index) {
    setState(() {
      _selectedIndex = index;
    });
  },
)

如果需要过渡动画,把点和连线的Container替换成AnimatedContainer,添加duration参数即可实现平滑切换效果。

二、使用现有Flutter包

如果不想手动写布局,这些现成包可以快速实现需求:

  • step_progress_indicator:专门做步骤式进度指示器,支持配置点的大小、连线粗细、颜色,适配TabBar场景
  • dots_indicator:原用于轮播指示器,调整参数后也能实现带连线的点式布局
  • timeline_tile:适合需要附加标签、图标等复杂样式的场景

以step_progress_indicator为例,基础使用示例:

StepProgressIndicator(
  totalSteps: 4,
  currentStep: _selectedIndex + 1,
  selectedColor: Colors.blue,
  unselectedColor: Colors.grey,
  size: 20,
  padding: const EdgeInsets.symmetric(horizontal: 16),
)

使用前需要在pubspec.yaml中添加对应依赖(版本号以官方最新为准)。

内容的提问来源于stack exchange,提问作者Shashank Deepak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:25:54