HydroNutrify_Ari_e41221567/lib/ui/shared/components/loading_indicator.dart

182 lines
4.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:mobile_monitoring/core/constants/colors.dart';
/// Loading Indicator - Widget untuk menampilkan loading state
class LoadingIndicator extends StatelessWidget {
final double size;
final Color? color;
final String? message;
const LoadingIndicator({
super.key,
this.size = 40,
this.color,
this.message,
});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
SizedBox(
width: size,
height: size,
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(
color ?? AppColors.primary,
),
strokeWidth: 3,
),
),
if (message != null) ...[
const SizedBox(height: 16),
Text(
message!,
style: const TextStyle(
fontSize: 14,
color: AppColors.textSecondary,
),
textAlign: TextAlign.center,
),
],
],
),
);
}
}
/// Overlay Loading - Full screen loading dengan overlay
class OverlayLoading extends StatelessWidget {
final String? message;
const OverlayLoading({
super.key,
this.message,
});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.black.withValues(alpha: 0.5),
child: Center(
child: Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(16),
),
child: LoadingIndicator(message: message),
),
),
);
}
}
/// Shimmer Loading - Shimmer effect untuk skeleton loading
class ShimmerLoading extends StatefulWidget {
final double width;
final double height;
final BorderRadius? borderRadius;
const ShimmerLoading({
super.key,
required this.width,
required this.height,
this.borderRadius,
});
@override
State<ShimmerLoading> createState() => _ShimmerLoadingState();
}
class _ShimmerLoadingState extends State<ShimmerLoading>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(milliseconds: 1500),
vsync: this,
)..repeat();
_animation = Tween<double>(begin: -1.0, end: 2.0).animate(
CurvedAnimation(parent: _controller, curve: Curves.easeInOut),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _animation,
builder: (context, child) {
return Container(
width: widget.width,
height: widget.height,
decoration: BoxDecoration(
borderRadius: widget.borderRadius ?? BorderRadius.circular(8),
gradient: LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: const [
AppColors.lightGray,
AppColors.white,
AppColors.lightGray,
],
stops: [
_animation.value - 0.3,
_animation.value,
_animation.value + 0.3,
],
),
),
);
},
);
}
}
/// Linear Progress Indicator - Progress bar
class CustomLinearProgress extends StatelessWidget {
final double? value;
final Color? backgroundColor;
final Color? valueColor;
final double height;
final BorderRadius? borderRadius;
const CustomLinearProgress({
super.key,
this.value,
this.backgroundColor,
this.valueColor,
this.height = 4,
this.borderRadius,
});
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: borderRadius ?? BorderRadius.circular(height / 2),
child: SizedBox(
height: height,
child: LinearProgressIndicator(
value: value,
backgroundColor: backgroundColor ?? AppColors.lightGray,
valueColor: AlwaysStoppedAnimation<Color>(
valueColor ?? AppColors.primary,
),
),
),
);
}
}