import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; class GradientSwitch extends StatefulWidget { final bool value; final Future Function(bool)? onChanged; final double width; final double height; final Duration animationDuration; final double indicatorSize; final LinearGradient selectedGradient; final LinearGradient unselectedGradient; final Color? loadingColor; const GradientSwitch({ super.key, required this.value, this.onChanged, this.width = 60.0, this.height = 30.0, this.animationDuration = const Duration(milliseconds: 300), this.indicatorSize = 24.0, this.selectedGradient = const LinearGradient(colors: [Colors.blue, Colors.purpleAccent]), this.unselectedGradient = const LinearGradient(colors: [Color(0xFFEEEEEE), Color(0xFFBDBDBD)]), this.loadingColor, }); @override State createState() => _GradientSwitchState(); } class _GradientSwitchState extends State with SingleTickerProviderStateMixin { late bool _currentValue; bool _isLoading = false; @override void initState() { super.initState(); _currentValue = widget.value; } @override void didUpdateWidget(GradientSwitch oldWidget) { super.didUpdateWidget(oldWidget); if (widget.value != _currentValue && !_isLoading) { _currentValue = widget.value; } } Future _handleTap() async { if (_isLoading || widget.onChanged == null) return; setState(() => _isLoading = true); final targetValue = !_currentValue; bool? success; try { success = await widget.onChanged!(targetValue); } finally { setState(() => _isLoading = false); if (success != null && mounted) { setState(() => _currentValue = success!); } } } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return GestureDetector( onTap: _handleTap, child: AnimatedContainer( duration: widget.animationDuration, width: widget.width, height: widget.height, decoration: BoxDecoration( borderRadius: BorderRadius.circular(widget.height / 2), gradient: _currentValue ? widget.selectedGradient : widget.unselectedGradient, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 4, offset: const Offset(0, 2), ) ], ), child: AnimatedAlign( duration: widget.animationDuration, alignment: _currentValue ? Alignment.centerRight : Alignment.centerLeft, child: Container( margin: const EdgeInsets.symmetric(horizontal: 3), width: widget.indicatorSize, height: widget.indicatorSize, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.2), blurRadius: 4, offset: const Offset(0, 2), ) ], ), child: _isLoading ? Center( child: CupertinoActivityIndicator( color: widget.loadingColor, radius: widget.indicatorSize * 0.3, ), ) : null, // 非加载状态不显示内容 ), ), ), ); } }