docs: Add more potential use case for Bottom Navigation Bar (#99644)
diff --git a/examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.2.dart b/examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.2.dart
new file mode 100644
index 0000000..ee5ebed
--- /dev/null
+++ b/examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.2.dart
@@ -0,0 +1,114 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flutter code sample for BottomNavigationBar
+
+import 'package:flutter/material.dart';
+
+void main() => runApp(const MyApp());
+
+class MyApp extends StatelessWidget {
+ const MyApp({super.key});
+
+ static const String _title = 'Flutter Code Sample';
+
+ @override
+ Widget build(BuildContext context) {
+ return const MaterialApp(
+ title: _title,
+ home: MyStatefulWidget(),
+ );
+ }
+}
+
+class MyStatefulWidget extends StatefulWidget {
+ const MyStatefulWidget({super.key});
+
+ @override
+ State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
+}
+
+class _MyStatefulWidgetState extends State<MyStatefulWidget> {
+ int _selectedIndex = 0;
+ final ScrollController _homeController = ScrollController();
+
+ Widget _listViewBody() {
+ return ListView.separated(
+ controller: _homeController,
+ itemBuilder: (BuildContext context, int index) {
+ return Center(
+ child: Text(
+ 'Item $index',
+ ),
+ );
+ },
+ separatorBuilder: (BuildContext context, int index) => const Divider(
+ thickness: 1,
+ ),
+ itemCount: 50);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('BottomNavigationBar Sample'),
+ ),
+ body: _listViewBody(),
+ bottomNavigationBar: BottomNavigationBar(
+ items: const <BottomNavigationBarItem>[
+ BottomNavigationBarItem(
+ icon: Icon(Icons.home),
+ label: 'Home',
+ ),
+ BottomNavigationBarItem(
+ icon: Icon(Icons.open_in_new_rounded),
+ label: 'Open Dialog',
+ ),
+ ],
+ currentIndex: _selectedIndex,
+ selectedItemColor: Colors.amber[800],
+ onTap: (int index) {
+ switch (index) {
+ case 0:
+ // only scroll to top when current index is selected.
+ if (_selectedIndex == index) {
+ _homeController.animateTo(
+ 0.0,
+ duration: const Duration(milliseconds: 500),
+ curve: Curves.easeOut,
+ );
+ }
+ break;
+ case 1:
+ showModal(context);
+ break;
+ }
+ setState(
+ () {
+ _selectedIndex = index;
+ },
+ );
+ },
+ ),
+ );
+ }
+
+ void showModal(BuildContext context) {
+ showDialog(
+ context: context,
+ builder: (BuildContext context) => AlertDialog(
+ content: const Text('Example Dialog'),
+ actions: <TextButton>[
+ TextButton(
+ onPressed: () {
+ Navigator.pop(context);
+ },
+ child: const Text('Close'),
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/examples/api/test/material/bottom_navigation_bar/bottom_navigation_bar.2.test.dart b/examples/api/test/material/bottom_navigation_bar/bottom_navigation_bar.2.test.dart
new file mode 100644
index 0000000..9d7788a
--- /dev/null
+++ b/examples/api/test/material/bottom_navigation_bar/bottom_navigation_bar.2.test.dart
@@ -0,0 +1,38 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter_api_samples/material/bottom_navigation_bar/bottom_navigation_bar.2.dart'
+ as example;
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('BottomNavigationBar Updates Screen Content',
+ (WidgetTester tester) async {
+ await tester.pumpWidget(
+ const example.MyApp(),
+ );
+
+ expect(find.widgetWithText(AppBar, 'BottomNavigationBar Sample'),
+ findsOneWidget);
+ expect(find.byType(BottomNavigationBar), findsOneWidget);
+ expect(find.widgetWithText(Center, 'Item 0'), findsOneWidget);
+
+ await tester.scrollUntilVisible(
+ find.widgetWithText(Center, 'Item 49'), 100);
+ await tester.pumpAndSettle();
+ expect(find.widgetWithText(Center, 'Item 49'), findsOneWidget);
+
+ await tester.tap(find.byIcon(Icons.home));
+ await tester.tap(find.byIcon(Icons.home));
+ await tester.pumpAndSettle();
+
+ final Scrollable bodyScrollView = tester.widget(find.byType(Scrollable));
+ expect(bodyScrollView.controller?.offset, 0.0);
+
+ await tester.tap(find.byIcon(Icons.open_in_new_rounded));
+ await tester.pumpAndSettle();
+ expect(find.byType(AlertDialog), findsOneWidget);
+ });
+}
diff --git a/packages/flutter/lib/src/material/bottom_navigation_bar.dart b/packages/flutter/lib/src/material/bottom_navigation_bar.dart
index 4880f82..82e05b7 100644
--- a/packages/flutter/lib/src/material/bottom_navigation_bar.dart
+++ b/packages/flutter/lib/src/material/bottom_navigation_bar.dart
@@ -118,6 +118,15 @@
///
/// ** See code in examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.1.dart **
/// {@end-tool}
+///
+/// {@tool dartpad}
+/// This example shows [BottomNavigationBar] used in a [Scaffold] Widget with
+/// different interaction patterns. Tapping twice on the first [BottomNavigationBarItem]
+/// uses the [ScrollController] to animate the [ListView] to the top. The second
+/// [BottomNavigationBarItem] shows a Modal Dialog.
+///
+/// ** See code in examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.2.dart **
+/// {@end-tool}
/// See also:
///
/// * [BottomNavigationBarItem]