Skip to content

Commit 3022db2

Browse files
authored
docs: Add more potential use case for Bottom Navigation Bar (#99644)
1 parent 912b81f commit 3022db2

File tree

3 files changed

+161
-0
lines changed

3 files changed

+161
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// Flutter code sample for BottomNavigationBar
6+
7+
import 'package:flutter/material.dart';
8+
9+
void main() => runApp(const MyApp());
10+
11+
class MyApp extends StatelessWidget {
12+
const MyApp({super.key});
13+
14+
static const String _title = 'Flutter Code Sample';
15+
16+
@override
17+
Widget build(BuildContext context) {
18+
return const MaterialApp(
19+
title: _title,
20+
home: MyStatefulWidget(),
21+
);
22+
}
23+
}
24+
25+
class MyStatefulWidget extends StatefulWidget {
26+
const MyStatefulWidget({super.key});
27+
28+
@override
29+
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
30+
}
31+
32+
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
33+
int _selectedIndex = 0;
34+
final ScrollController _homeController = ScrollController();
35+
36+
Widget _listViewBody() {
37+
return ListView.separated(
38+
controller: _homeController,
39+
itemBuilder: (BuildContext context, int index) {
40+
return Center(
41+
child: Text(
42+
'Item $index',
43+
),
44+
);
45+
},
46+
separatorBuilder: (BuildContext context, int index) => const Divider(
47+
thickness: 1,
48+
),
49+
itemCount: 50);
50+
}
51+
52+
@override
53+
Widget build(BuildContext context) {
54+
return Scaffold(
55+
appBar: AppBar(
56+
title: const Text('BottomNavigationBar Sample'),
57+
),
58+
body: _listViewBody(),
59+
bottomNavigationBar: BottomNavigationBar(
60+
items: const <BottomNavigationBarItem>[
61+
BottomNavigationBarItem(
62+
icon: Icon(Icons.home),
63+
label: 'Home',
64+
),
65+
BottomNavigationBarItem(
66+
icon: Icon(Icons.open_in_new_rounded),
67+
label: 'Open Dialog',
68+
),
69+
],
70+
currentIndex: _selectedIndex,
71+
selectedItemColor: Colors.amber[800],
72+
onTap: (int index) {
73+
switch (index) {
74+
case 0:
75+
// only scroll to top when current index is selected.
76+
if (_selectedIndex == index) {
77+
_homeController.animateTo(
78+
0.0,
79+
duration: const Duration(milliseconds: 500),
80+
curve: Curves.easeOut,
81+
);
82+
}
83+
break;
84+
case 1:
85+
showModal(context);
86+
break;
87+
}
88+
setState(
89+
() {
90+
_selectedIndex = index;
91+
},
92+
);
93+
},
94+
),
95+
);
96+
}
97+
98+
void showModal(BuildContext context) {
99+
showDialog(
100+
context: context,
101+
builder: (BuildContext context) => AlertDialog(
102+
content: const Text('Example Dialog'),
103+
actions: <TextButton>[
104+
TextButton(
105+
onPressed: () {
106+
Navigator.pop(context);
107+
},
108+
child: const Text('Close'),
109+
)
110+
],
111+
),
112+
);
113+
}
114+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:flutter/material.dart';
6+
import 'package:flutter_api_samples/material/bottom_navigation_bar/bottom_navigation_bar.2.dart'
7+
as example;
8+
import 'package:flutter_test/flutter_test.dart';
9+
10+
void main() {
11+
testWidgets('BottomNavigationBar Updates Screen Content',
12+
(WidgetTester tester) async {
13+
await tester.pumpWidget(
14+
const example.MyApp(),
15+
);
16+
17+
expect(find.widgetWithText(AppBar, 'BottomNavigationBar Sample'),
18+
findsOneWidget);
19+
expect(find.byType(BottomNavigationBar), findsOneWidget);
20+
expect(find.widgetWithText(Center, 'Item 0'), findsOneWidget);
21+
22+
await tester.scrollUntilVisible(
23+
find.widgetWithText(Center, 'Item 49'), 100);
24+
await tester.pumpAndSettle();
25+
expect(find.widgetWithText(Center, 'Item 49'), findsOneWidget);
26+
27+
await tester.tap(find.byIcon(Icons.home));
28+
await tester.tap(find.byIcon(Icons.home));
29+
await tester.pumpAndSettle();
30+
31+
final Scrollable bodyScrollView = tester.widget(find.byType(Scrollable));
32+
expect(bodyScrollView.controller?.offset, 0.0);
33+
34+
await tester.tap(find.byIcon(Icons.open_in_new_rounded));
35+
await tester.pumpAndSettle();
36+
expect(find.byType(AlertDialog), findsOneWidget);
37+
});
38+
}

packages/flutter/lib/src/material/bottom_navigation_bar.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ enum BottomNavigationBarLandscapeLayout {
118118
///
119119
/// ** See code in examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.1.dart **
120120
/// {@end-tool}
121+
///
122+
/// {@tool dartpad}
123+
/// This example shows [BottomNavigationBar] used in a [Scaffold] Widget with
124+
/// different interaction patterns. Tapping twice on the first [BottomNavigationBarItem]
125+
/// uses the [ScrollController] to animate the [ListView] to the top. The second
126+
/// [BottomNavigationBarItem] shows a Modal Dialog.
127+
///
128+
/// ** See code in examples/api/lib/material/bottom_navigation_bar/bottom_navigation_bar.2.dart **
129+
/// {@end-tool}
121130
/// See also:
122131
///
123132
/// * [BottomNavigationBarItem]

0 commit comments

Comments
 (0)