Flutter实现可旋转半圆形无限轮播指示器技术咨询
实现可旋转的无限半圆形轮播指示器
需求说明
- 实现支持顺时针、逆时针旋转的无限半圆形轮播指示器
- 要求选中状态的彩色标记始终处于中间位置
当前实现代码(可在Dart Pad运行)
//Full circle with colored dast at the bottom import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Dashed Circle Demo', theme: ThemeData(primarySwatch: Colors.blue), home: Scaffold( appBar: AppBar(title: Text('Dashed Circle')), body: Center(child: DashedCircleWithControls()), ), ); } } class DashedCircleWithControls extends StatefulWidget { @override _DashedCircleWithControlsState createState() => _DashedCircleWithControlsState(); } class _DashedCircleWithControlsState extends State<DashedCircleWithControls> with SingleTickerProviderStateMixin { late AnimationController _controller; double _rotationAngle = 0.0; final double _rotationStep = 0.7; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: Duration(milliseconds: 200), ); } @override void dispose() { _controller.dispose(); super.dispose(); } void _rotateForward() { setState(() { _rotationAngle += _rotationStep; _controller.forward(from: 0.0); }); } void _rotateBackward() { setState(() { _rotationAngle -= _rotationStep; _controller.forward(from: 0.0); }); } @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Stack( alignment: Alignment.center, children: [ // 旋转的虚线圆环 AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.rotate( angle: _rotationAngle, child: CustomPaint( size: Size(200, 200), painter: RotatingDashedCirclePainter(), ), ); }, ), // 固定的彩色标记(始终在右侧) CustomPaint( size: Size(200, 200), painter: FixedColoredDashPainter(), ), ], ), SizedBox(height: 20), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: Icon(Icons.remove, size: 32), onPressed: _rotateBackward, color: Colors.red, ), SizedBox(width: 40), IconButton( icon: Icon(Icons.add, size: 32), onPressed: _rotateForward, color: Colors.green, ), ], ), ], ); } } class RotatingDashedCirclePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2 - 10; final paint = Paint() ..color = Colors.grey ..strokeWidth = 2 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; const dashCount = 38; const dashAngle = 2 * 3.14159 / dashCount; const dashLength = 0.7; for (int i = 0; i < dashCount; i++) { final startAngle = i * dashAngle; // 跳过绘制右侧(3点钟位置)的虚线 // if (i >= 0 && i <= 15) continue; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, dashAngle * dashLength, false, paint, ); } } @override bool shouldRepaint(CustomPainter oldDelegate) => false; } class FixedColoredDashPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 2 - 10; final paint = Paint() ..color = Colors.blue ..strokeWidth = 6 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round; const dashCount = 38; const dashAngle = 2 * 3.14 / dashCount; const dashLength = 0.7; // 只绘制右侧(3点钟位置)的彩色标记 // Flutter坐标系中0弧度对应右侧 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), (3.141592654 / 2.0) - 0.05, // 起始于0弧度(右侧) dashAngle * dashLength, false, paint, ); } @override bool shouldRepaint(CustomPainter oldDelegate) => false; }
内容的提问来源于stack exchange,提问作者Muhammad Faizan
相关产品推荐
相关产品推荐

