232 lines
5.5 KiB
Dart
Executable File
232 lines
5.5 KiB
Dart
Executable File
import 'package:flutter/material.dart';
|
||
|
||
/// 简单的加载动画组件,替代有问题的flutter_spinkit
|
||
class KRSimpleLoading extends StatefulWidget {
|
||
final Color? color;
|
||
final double size;
|
||
final Duration duration;
|
||
|
||
const KRSimpleLoading({
|
||
super.key,
|
||
this.color,
|
||
this.size = 40.0,
|
||
this.duration = const Duration(milliseconds: 1000),
|
||
});
|
||
|
||
@override
|
||
State<KRSimpleLoading> createState() => _KRSimpleLoadingState();
|
||
}
|
||
|
||
class _KRSimpleLoadingState extends State<KRSimpleLoading>
|
||
with SingleTickerProviderStateMixin {
|
||
late AnimationController _controller;
|
||
late Animation<double> _animation;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_controller = AnimationController(
|
||
duration: widget.duration,
|
||
vsync: this,
|
||
);
|
||
_animation = Tween<double>(
|
||
begin: 0.0,
|
||
end: 1.0,
|
||
).animate(CurvedAnimation(
|
||
parent: _controller,
|
||
curve: Curves.easeInOut,
|
||
));
|
||
_controller.repeat();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_controller.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return AnimatedBuilder(
|
||
animation: _animation,
|
||
builder: (context, child) {
|
||
return Transform.rotate(
|
||
angle: _animation.value * 2 * 3.14159,
|
||
child: Container(
|
||
width: widget.size,
|
||
height: widget.size,
|
||
decoration: BoxDecoration(
|
||
shape: BoxShape.circle,
|
||
border: Border.all(
|
||
color: widget.color ?? Theme.of(context).primaryColor,
|
||
width: 2.0,
|
||
),
|
||
),
|
||
child: Padding(
|
||
padding: const EdgeInsets.all(2.0),
|
||
child: CircularProgressIndicator(
|
||
strokeWidth: 2.0,
|
||
valueColor: AlwaysStoppedAnimation<Color>(
|
||
widget.color ?? Theme.of(context).primaryColor,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 脉冲加载动画
|
||
class KRSimplePulse extends StatefulWidget {
|
||
final Color? color;
|
||
final double size;
|
||
final Duration duration;
|
||
|
||
const KRSimplePulse({
|
||
super.key,
|
||
this.color,
|
||
this.size = 40.0,
|
||
this.duration = const Duration(milliseconds: 1500),
|
||
});
|
||
|
||
@override
|
||
State<KRSimplePulse> createState() => _KRSimplePulseState();
|
||
}
|
||
|
||
class _KRSimplePulseState extends State<KRSimplePulse>
|
||
with SingleTickerProviderStateMixin {
|
||
late AnimationController _controller;
|
||
late Animation<double> _animation;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_controller = AnimationController(
|
||
duration: widget.duration,
|
||
vsync: this,
|
||
);
|
||
_animation = Tween<double>(
|
||
begin: 0.0,
|
||
end: 1.0,
|
||
).animate(CurvedAnimation(
|
||
parent: _controller,
|
||
curve: Curves.easeInOut,
|
||
));
|
||
_controller.repeat();
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_controller.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return AnimatedBuilder(
|
||
animation: _animation,
|
||
builder: (context, child) {
|
||
return Transform.scale(
|
||
scale: 0.5 + (_animation.value * 0.5),
|
||
child: Opacity(
|
||
opacity: 1.0 - _animation.value,
|
||
child: Container(
|
||
width: widget.size,
|
||
height: widget.size,
|
||
decoration: BoxDecoration(
|
||
shape: BoxShape.circle,
|
||
color: widget.color ?? Theme.of(context).primaryColor,
|
||
),
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 波浪加载动画
|
||
class KRSimpleWave extends StatefulWidget {
|
||
final Color? color;
|
||
final double size;
|
||
final Duration duration;
|
||
|
||
const KRSimpleWave({
|
||
super.key,
|
||
this.color,
|
||
this.size = 40.0,
|
||
this.duration = const Duration(milliseconds: 1200),
|
||
});
|
||
|
||
@override
|
||
State<KRSimpleWave> createState() => _KRSimpleWaveState();
|
||
}
|
||
|
||
class _KRSimpleWaveState extends State<KRSimpleWave>
|
||
with TickerProviderStateMixin {
|
||
late List<AnimationController> _controllers;
|
||
late List<Animation<double>> _animations;
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
_controllers = List.generate(3, (index) {
|
||
return AnimationController(
|
||
duration: widget.duration,
|
||
vsync: this,
|
||
);
|
||
});
|
||
|
||
_animations = _controllers.map((controller) {
|
||
return Tween<double>(
|
||
begin: 0.0,
|
||
end: 1.0,
|
||
).animate(CurvedAnimation(
|
||
parent: controller,
|
||
curve: Curves.easeInOut,
|
||
));
|
||
}).toList();
|
||
|
||
for (int i = 0; i < _controllers.length; i++) {
|
||
Future.delayed(Duration(milliseconds: i * 200), () {
|
||
if (mounted) {
|
||
_controllers[i].repeat();
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
for (var controller in _controllers) {
|
||
controller.dispose();
|
||
}
|
||
super.dispose();
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Row(
|
||
mainAxisSize: MainAxisSize.min,
|
||
children: List.generate(3, (index) {
|
||
return AnimatedBuilder(
|
||
animation: _animations[index],
|
||
builder: (context, child) {
|
||
return Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 2.0),
|
||
width: widget.size / 6,
|
||
height: widget.size * (0.3 + (_animations[index].value * 0.7)),
|
||
decoration: BoxDecoration(
|
||
color: widget.color ?? Theme.of(context).primaryColor,
|
||
borderRadius: BorderRadius.circular(2.0),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}),
|
||
);
|
||
}
|
||
}
|