如何为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
相关产品推荐
相关产品推荐

