import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';
// // 사용 예시
// Container(
// width: 64.w,
// height: 64.w,
// decoration: BoxDecoration(
// color: staff.TRColors.SplashBackground,
// borderRadius: BorderRadius.circular(180),
// ),
// child: JumpingDotsProgressIndicator(
// dotSpacing: 8.w,
// fontSize: 8.w,
// color: TRColors.button_white,
// ),
// ),
class _JumpingDot extends AnimatedWidget {
final Color? color;
final double? fontSize;
const _JumpingDot(
{Key? key,
required Animation<double> animation,
this.color,
this.fontSize})
: super(key: key, listenable: animation);
Widget build(BuildContext context) {
final Animation<double> animation = listenable as Animation<double>;
return SizedBox(
height: animation.value + fontSize!,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 사이즈 고정
Container(
width: fontSize!,
height: fontSize!,
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.circular(50),
),
),
],
),
);
}
}
class JumpingDotsLoading extends StatefulWidget {
/// 로딩 Dots 숫자 기본 = 3.
final int numberOfDots;
/// 사이즈
final double fontSize;
/// Dots 사이 공백, default 0.0.
final double dotSpacing;
/// Dots 색, default black.
final Color color;
/// Animation 시간, default 250 milliseconds.
final int milliseconds;
/// Animations 의 시작과 끝 크기.
final double beginTweenValue;
final double endTweenValue;
final Curve animationCurve;
/// Creates a jumping do progress indicator.
JumpingDotsLoading({
required this.fontSize,
required this.dotSpacing,
this.beginTweenValue = 0.0,
this.endTweenValue = 30.0,
this.animationCurve = Curves.easeInOut,
this.numberOfDots = 3,
this.color = Colors.black,
this.milliseconds = 250,
});
_JumpingDotsLoadingState createState() => _JumpingDotsLoadingState(
numberOfDots: this.numberOfDots,
fontSize: this.fontSize,
color: this.color,
dotSpacing: this.dotSpacing,
milliseconds: this.milliseconds,
);
}
class _JumpingDotsLoadingState extends State<JumpingDotsLoading>
with TickerProviderStateMixin {
int? numberOfDots;
int? milliseconds;
double fontSize;
double dotSpacing;
Color? color;
List<AnimationController> controllers = <AnimationController>[];
List<Animation<double>> animations = <Animation<double>>[];
List<Widget> _widgets = <Widget>[];
_JumpingDotsLoadingState({
this.numberOfDots,
required this.fontSize,
this.color,
required this.dotSpacing,
this.milliseconds,
});
@override
initState() {
super.initState();
for (int i = 0; i < numberOfDots!; i++) {
_addAnimationControllers();
_buildAnimations(i);
_addListOfDots(i);
}
controllers[0].forward();
}
@override
dispose() {
for (int i = 0; i < numberOfDots!; i++) controllers[i].dispose();
super.dispose();
}
void _addAnimationControllers() {
controllers.add(AnimationController(
duration: Duration(milliseconds: milliseconds!), vsync: this));
}
void _addListOfDots(int index) {
_widgets.add(
Padding(
padding: EdgeInsets.symmetric(horizontal: dotSpacing! / 2),
child: _JumpingDot(
animation: animations[index],
fontSize: fontSize,
color: color,
),
),
);
}
void _buildAnimations(int index) {
animations.add(
Tween(begin: widget.beginTweenValue, end: widget.endTweenValue).animate(
CurvedAnimation(
parent: controllers[index], curve: widget.animationCurve))
// .animate(controllers[index])
..addStatusListener(
(AnimationStatus status) {
if (status == AnimationStatus.completed)
controllers[index].reverse();
if (index == numberOfDots! - 1 &&
status == AnimationStatus.dismissed) {
controllers[0].forward();
}
if (animations[index].value > widget.endTweenValue / 2 &&
index < numberOfDots! - 1) {
controllers[index + 1].forward();
}
},
),
);
}
Widget build(BuildContext context) {
return SizedBox(
height: fontSize,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _widgets,
),
);
}
}