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

如何为smooth_page_indicator组件添加轮廓边框并设置内填充色

smooth_page_indicator 实现空心描边未选中、实心填充选中圆点效果

问题背景

当前使用smooth_page_indicator插件开发页面指示器,目标效果为:

  • 未选中圆点:灰色描边,内部透明
  • 选中圆点:灰色实心填充
    参考效果如下:
    预期效果参考图

实际开发中设置PaintingStyle.stroke后所有圆点都变成空心描边,不符合预期,实际效果如下:
实际实现效果图

原有问题代码:

child: SmoothPageIndicator(
                controller: controller,
                count: 3,
                effect: ScrollingDotsEffect(
                  paintStyle: PaintingStyle.stroke,
                  dotColor: Color(0xFFACACAC),
                  activeDotColor: Color(0xFFACACAC),
                ),
                onDotClicked: (index) => controller.animateToPage(
                  index,
                  duration: Duration(milliseconds: 500),
                  curve: Curves.easeIn,
                ),
              ),

解决方法

问题根源:内置ScrollingDotsEffect的paintStyle为全局配置,会同时作用于选中、未选中圆点,没有提供单独区分两类圆点绘制样式的参数,因此仅修改activeDotColor无法实现填充效果。

通过自定义继承自ScrollingDotsEffect的效果类,重写绘制逻辑,给未选中点配置描边画笔、选中点配置填充画笔即可实现目标效果:

  • 编写自定义效果类
import 'package:flutter/material.dart';
import 'package:smooth_page_indicator/smooth_page_indicator.dart';

class CustomScrollingDotsEffect extends ScrollingDotsEffect {
  const CustomScrollingDotsEffect({
    super.dotColor = const Color(0xFFACACAC),
    super.activeDotColor = const Color(0xFFACACAC),
    super.dotWidth = 10,
    super.dotHeight = 10,
    super.strokeWidth = 1.5,
    super.activeDotScale = 1,
    super.spacing = 8,
    super.radius,
    super.activeStrokeWidth,
    super.paintStyle,
  });

  @override
  void paint(Canvas canvas, Size size, double offset, Size dotSize,
      int count, double dotRadius, Paint paint) {
    // 未选中点画笔:空心描边
    final inactivePaint = Paint()
      ..color = dotColor
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth;
    // 选中点画笔:实心填充
    final activePaint = Paint()
      ..color = activeDotColor
      ..style = PaintingStyle.fill;

    for (int i = 0; i < count; i++) {
      final dotPos = Offset(
        i * (dotSize.width + spacing) + dotSize.width / 2,
        size.height / 2,
      );
      // 保留原组件滚动缩放动效逻辑
      final scale = 1.0 + (activeDotScale - 1.0) * (1 - (offset - i).abs().clamp(0.0, 1.0));
      final currentRadius = dotRadius * scale;

      if (i == offset.round()) {
        canvas.drawCircle(dotPos, currentRadius, activePaint);
      } else {
        canvas.drawCircle(dotPos, dotRadius, inactivePaint);
      }
    }
  }
}
  • 替换原有ScrollingDotsEffect配置,使用自定义效果
child: SmoothPageIndicator(
  controller: controller,
  count: 3,
  effect: const CustomScrollingDotsEffect(
    dotColor: Color(0xFFACACAC),
    activeDotColor: Color(0xFFACACAC),
    strokeWidth: 1.5, // 可按需调整边框粗细
    activeDotScale: 1, // 不需要选中点放大效果时设为1,与参考效果一致
  ),
  onDotClicked: (index) => controller.animateToPage(
    index,
    duration: const Duration(milliseconds: 500),
    curve: Curves.easeIn,
  ),
),

如果不需要滚动圆点的位移动效,也可以用同样逻辑继承其他内置Effect(如ExpandingDotsEffect、WormEffect)重写paint方法,适配需要的动效即可。


内容的提问来源于stack exchange,提问作者Lucky Ugwu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 20:19:01