91 lines
2.6 KiB
Dart
91 lines
2.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
class GradientSwitch extends StatefulWidget {
|
|
final bool value;
|
|
final ValueChanged<bool> onChanged;
|
|
final Gradient activeGradient;
|
|
final Color inactiveColor;
|
|
final Color activeThumbColor;
|
|
final Color inactiveThumbColor;
|
|
|
|
const GradientSwitch({
|
|
super.key,
|
|
required this.value,
|
|
required this.onChanged,
|
|
required this.activeGradient,
|
|
this.inactiveColor = Colors.grey,
|
|
this.activeThumbColor = Colors.white,
|
|
this.inactiveThumbColor = Colors.white,
|
|
});
|
|
|
|
@override
|
|
State<GradientSwitch> createState() => _GradientSwitchState();
|
|
}
|
|
|
|
class _GradientSwitchState extends State<GradientSwitch>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(
|
|
vsync: this, duration: const Duration(milliseconds: 200));
|
|
_controller.value = widget.value ? 1.0 : 0.0;
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(covariant GradientSwitch oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (widget.value != oldWidget.value) {
|
|
widget.value ? _controller.forward() : _controller.reverse();
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return GestureDetector(
|
|
onTap: () => widget.onChanged(!widget.value),
|
|
child: AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
final align = Alignment.lerp(
|
|
Alignment.centerLeft, Alignment.centerRight, _controller.value)!;
|
|
|
|
// 动态计算小球颜色(线性过渡)
|
|
final thumbColor = Color.lerp(widget.inactiveThumbColor,
|
|
widget.activeThumbColor, _controller.value)!;
|
|
|
|
return Container(
|
|
width: 60,
|
|
height: 30,
|
|
padding: const EdgeInsets.all(3),
|
|
decoration: BoxDecoration(
|
|
borderRadius: BorderRadius.circular(30),
|
|
gradient: widget.value ? widget.activeGradient : null,
|
|
color: widget.value ? null : widget.inactiveColor,
|
|
),
|
|
child: Align(
|
|
alignment: align,
|
|
child: Container(
|
|
width: 24,
|
|
height: 24,
|
|
decoration: BoxDecoration(
|
|
color: thumbColor,
|
|
shape: BoxShape.circle,
|
|
boxShadow: const [
|
|
BoxShadow(
|
|
color: Colors.black26,
|
|
blurRadius: 2,
|
|
offset: Offset(0, 1)),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|