import 'package:flutter/material.dart'; import 'package:test_sa/animations/number_incremental_animation.dart'; import 'package:test_sa/new_views/app_style/app_color.dart'; class CustomBadge extends StatelessWidget { final Widget child; // The widget that the badge will be overlaid on. final int value; // The value or text to be displayed in the badge. final Color color; final double? positionR; final double? positionT; final double? height; final double? width; CustomBadge({ Key? key, required this.child, required this.value, this.height, this.width, this.positionR, this.positionT, this.color = AppColor.red30, // Default color is red }) : super(key: key); @override Widget build(BuildContext context) { return Stack( clipBehavior: Clip.none, // Allows the badge to overflow its container. children: [ child, // The main widget // if (value > 0) Positioned( right: positionR ?? -6, top: positionT ?? -6, //Need to check why opacity he used here this is not correct need to make this total dynamic and responsive child: Opacity( opacity: value > 0 ? 1 : 0, child: Container( height: height ?? 23, constraints: BoxConstraints(minWidth: width ?? 23), padding: const EdgeInsets.all(3), alignment: Alignment.center, decoration: BoxDecoration(color: color, borderRadius: BorderRadius.circular(30)), child: CounterAnimatedText( value: value, style: const TextStyle(color: AppColor.white10, fontFamily: 'Poppins', fontSize: 10, fontWeight: FontWeight.w700), ), ), ), ), ], ); } } //Need to use this badge every where.. class CustomBadge2 extends StatelessWidget { final Widget child; final int value; final double top; final double right; final double left; final double bottom; final double minSize; final Color backgroundColor; final Color textColor; final TextStyle? textStyle; final int maxValue; final Duration animationDuration; const CustomBadge2({ super.key, required this.child, required this.value, this.top = -6, this.right = -6, this.left = double.nan, this.bottom = double.nan, this.minSize = 18, this.backgroundColor = AppColor.red30, this.textColor = AppColor.white10, this.textStyle, this.maxValue = 99, this.animationDuration = const Duration(milliseconds: 200), }); bool get _isVisible => value > 0; @override Widget build(BuildContext context) { return Stack( clipBehavior: Clip.none, children: [ child, if (_isVisible) Positioned( top: top.isNaN ? null : top, right: right.isNaN ? null : right, left: left.isNaN ? null : left, bottom: bottom.isNaN ? null : bottom, child: AnimatedScale( scale: _isVisible ? 1 : 0, duration: animationDuration, curve: Curves.easeOutBack, child: AnimatedOpacity( opacity: _isVisible ? 1 : 0, duration: animationDuration, child: _Badge( value: value, maxValue: maxValue, minSize: minSize, backgroundColor: backgroundColor, textColor: textColor, textStyle: textStyle ?? Theme.of(context).textTheme.labelSmall?.copyWith( fontWeight: FontWeight.w700, ), ), ), ), ), ], ); } } class _Badge extends StatelessWidget { final int value; final int maxValue; final double minSize; final Color backgroundColor; final Color textColor; final TextStyle? textStyle; const _Badge({ required this.value, required this.maxValue, required this.minSize, required this.backgroundColor, required this.textColor, this.textStyle, }); bool get _isOverflow => value > maxValue; @override Widget build(BuildContext context) { final TextStyle baseStyle = (textStyle ?? Theme.of(context).textTheme.labelMedium)!.copyWith( color: textColor, fontWeight: FontWeight.w700, ); final double badgeSize = minSize; return IgnorePointer( child: SizedBox( width: badgeSize, height: badgeSize, child: DecoratedBox( decoration: const BoxDecoration( shape: BoxShape.circle, ), child: DecoratedBox( decoration: BoxDecoration( color: backgroundColor, shape: BoxShape.circle, ), child: Center( child: _isOverflow ? FittedBox( child: Text( '$maxValue+', style: baseStyle.copyWith( fontSize: badgeSize * 0.45, ), ), ) : CounterAnimatedText( value: value, style: baseStyle.copyWith( fontSize: badgeSize * 0.6, ), ), ), ), ), ), ); } }