如何在Flutter中实现Neuromorphic风格的CircularSlider圆形滑块
新拟态风格圆形滑块实现方案
核心实现逻辑
- 弃用
sleek_circular_slider的默认样式渲染,仅使用它的手势监听、进度计算、角度换算基础能力 - 用
flutter_neumorphic的Neumorphic组件绘制底层轨道、上层进度轨道、可拖动旋钮的新拟态效果 - 通过
sleek_circular_slider的onChange回调实时更新进度值,同步刷新自定义的新拟态UI元素
1. 添加依赖
在pubspec.yaml中添加以下稳定版本依赖:
dependencies: flutter: sdk: flutter flutter_neumorphic: ^3.2.0 sleek_circular_slider: ^2.0.1
2. 完整可运行示例代码
import 'dart:math'; import 'package:flutter/material.dart'; import 'package:flutter_neumorphic/flutter_neumorphic.dart'; import 'package:sleek_circular_slider/sleek_circular_slider.dart'; class NeumorphicCircularSlider extends StatefulWidget { const NeumorphicCircularSlider({super.key}); @override State<NeumorphicCircularSlider> createState() => _NeumorphicCircularSliderState(); } class _NeumorphicCircularSliderState extends State<NeumorphicCircularSlider> { double _currentValue = 50; final double _maxValue = 100; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: NeumorphicTheme.baseColor(context), body: Center( child: SizedBox( width: 250, height: 250, child: Stack( alignment: Alignment.center, children: [ // 新拟态底层轨道 Neumorphic( style: NeumorphicStyle( shape: NeumorphicShape.flat, boxShape: const NeumorphicBoxShape.circle(), depth: -3, intensity: 0.8, color: NeumorphicTheme.baseColor(context), ), child: const SizedBox(width: 250, height: 250), ), // 新拟态进度轨道 SizedBox( width: 250, height: 250, child: CustomPaint( painter: _NeumorphicProgressPainter( progress: _currentValue / _maxValue, baseColor: NeumorphicTheme.baseColor(context), ), ), ), // 透明的sleek滑块,仅保留手势能力 SleekCircularSlider( min: 0, max: _maxValue, initialValue: _currentValue, appearance: CircularSliderAppearance( customWidths: CustomSliderWidths( trackWidth: 20, progressBarWidth: 20, handlerSize: 25, ), customColors: CustomSliderColors( trackColor: Colors.transparent, progressBarColor: Colors.transparent, hideShadow: true, dotColor: Colors.transparent, ), ), onChange: (value) { setState(() { _currentValue = value; }); }, innerWidget: (value) { return Center( child: NeumorphicText( "${value.round()}", style: const NeumorphicStyle( depth: 2, intensity: 0.8, ), textStyle: NeumorphicTextStyle( fontSize: 48, fontWeight: FontWeight.bold, ), ), ); }, ), // 新拟态滑块旋钮 _buildNeumorphicHandler(), ], ), ), ), ); } Widget _buildNeumorphicHandler() { final angle = (_currentValue / _maxValue) * 2 * pi - pi / 2; final radius = 250 / 2 - 10; final dx = radius * cos(angle); final dy = radius * sin(angle); return Transform.translate( offset: Offset(dx, dy), child: Neumorphic( style: const NeumorphicStyle( shape: NeumorphicShape.convex, boxShape: NeumorphicBoxShape.circle(), depth: 4, intensity: 0.9, ), child: const SizedBox(width: 22, height: 22), ), ); } } class _NeumorphicProgressPainter extends CustomPainter { final double progress; final Color baseColor; _NeumorphicProgressPainter({required this.progress, required this.baseColor}); @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() ..style = PaintingStyle.stroke ..strokeWidth = 18 ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 2); // 模拟新拟态高亮进度边 canvas.drawArc( Rect.fromCircle(center: center, radius: radius), -pi / 2, progress * 2 * pi, false, paint..color = Colors.white.withOpacity(0.7), ); // 模拟新拟态阴影进度边 canvas.drawArc( Rect.fromCircle(center: center, radius: radius + 1.2), -pi / 2, progress * 2 * pi, false, paint..color = Colors.black.withOpacity(0.2), ); } @override bool shouldRepaint(covariant _NeumorphicProgressPainter oldDelegate) { return oldDelegate.progress != progress; } }
效果参考

内容的提问来源于stack exchange,提问作者Исфан Джамалутдинов
相关产品推荐
相关产品推荐

