Added Badge.count constructor (#115297)

diff --git a/packages/flutter/lib/src/material/badge.dart b/packages/flutter/lib/src/material/badge.dart
index e4fd4c2..2c81567 100644
--- a/packages/flutter/lib/src/material/badge.dart
+++ b/packages/flutter/lib/src/material/badge.dart
@@ -40,6 +40,24 @@
     this.child,
   });
 
+  /// Convenience constructor for creating a badge with a numeric
+  /// label with 1-3 digits based on [count].
+  ///
+  /// Initializes [label] with a [Text] widget that contains [count].
+  /// If [count] is greater than 999, then the label is '999+'.
+  Badge.count({
+    super.key,
+    this.backgroundColor,
+    this.textColor,
+    this.smallSize,
+    this.largeSize,
+    this.textStyle,
+    this.padding,
+    this.alignment,
+    required int count,
+    this.child,
+  }) : label = Text(count > 999 ? '999+' : '$count');
+
   /// The badge's fill color.
   ///
   /// Defaults to the [BadgeTheme]'s background color, or
diff --git a/packages/flutter/test/material/badge_test.dart b/packages/flutter/test/material/badge_test.dart
index b5de837..6de9f4c 100644
--- a/packages/flutter/test/material/badge_test.dart
+++ b/packages/flutter/test/material/badge_test.dart
@@ -111,6 +111,63 @@
     expect(box, paints..rrect(rrect: RRect.fromLTRBR(-8, -4, 12, 12, const Radius.circular(8)), color: theme.colorScheme.error));
   });
 
+  // Essentially the same as 'Large Badge defaults'
+  testWidgets('Badge.count', (WidgetTester tester) async {
+    late final ThemeData theme;
+
+    Widget buildFrame(int count) {
+      return MaterialApp(
+        theme: ThemeData.light(useMaterial3: true),
+        home: Align(
+          alignment: Alignment.topLeft,
+          child: Builder(
+            builder: (BuildContext context) {
+              // theme.textTheme is updated when the MaterialApp is built.
+              if (count == 0) {
+                theme = Theme.of(context);
+              }
+              return Badge.count(
+                count: count,
+                child: const Icon(Icons.add),
+              );
+            },
+          ),
+        ),
+      );
+    }
+
+    await tester.pumpWidget(buildFrame(0));
+
+    expect(
+      tester.renderObject<RenderParagraph>(find.text('0')).text.style,
+      theme.textTheme.labelSmall!.copyWith(color: theme.colorScheme.onError),
+    );
+
+    // default badge alignment = AlignmentDirectional(12, -4)
+    // default padding = EdgeInsets.symmetric(horizontal: 4)
+    // default largeSize = 16
+    // '0'.width = 12
+    // icon.width = 24
+
+    expect(tester.getSize(find.byType(Badge)), const Size(24, 24)); // default Icon size
+    expect(tester.getTopLeft(find.byType(Badge)), Offset.zero);
+
+    // x = alignment.start + padding.left
+    // y = alignment.top
+    expect(tester.getTopLeft(find.text('0')), const Offset(16, -4));
+
+    final RenderBox box = tester.renderObject(find.byType(Badge));
+    // '0'.width = 12
+    // L = alignment.start
+    // T = alignment.top
+    // R = L + '0'.width + padding.width
+    // B = T + largeSize, R = largeSize/2
+    expect(box, paints..rrect(rrect: RRect.fromLTRBR(12, -4, 32, 12, const Radius.circular(8)), color: theme.colorScheme.error));
+
+    await tester.pumpWidget(buildFrame(1000));
+    expect(find.text('999+'), findsOneWidget);
+  });
+
   testWidgets('Small Badge defaults', (WidgetTester tester) async {
     final ThemeData theme = ThemeData.light(useMaterial3: true);