Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
f07db401
Unverified
Commit
f07db401
authored
Dec 14, 2022
by
Taha Tesser
Committed by
GitHub
Dec 14, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
`NavigationBar` improvements (#116992)
parent
f0ea3764
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
681 additions
and
435 deletions
+681
-435
navigation_bar.0.dart
...les/api/lib/material/navigation_bar/navigation_bar.0.dart
+3
-3
navigation_bar.1.dart
...les/api/lib/material/navigation_bar/navigation_bar.1.dart
+65
-334
navigation_bar.2.dart
...les/api/lib/material/navigation_bar/navigation_bar.2.dart
+367
-0
navigation_bar.0_test.dart
...i/test/material/navigation_bar/navigation_bar.0_test.dart
+2
-3
navigation_bar.1_test.dart
...i/test/material/navigation_bar/navigation_bar.1_test.dart
+23
-88
navigation_bar.2_test.dart
...i/test/material/navigation_bar/navigation_bar.2_test.dart
+108
-0
navigation_bar.dart
packages/flutter/lib/src/material/navigation_bar.dart
+21
-5
navigation_bar_test.dart
packages/flutter/test/material/navigation_bar_test.dart
+92
-2
No files found.
examples/api/lib/material/navigation_bar/navigation_bar.0.dart
View file @
f07db401
...
...
@@ -6,10 +6,10 @@
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
Example
App
());
void
main
(
)
=>
runApp
(
const
NavigationBar
App
());
class
Example
App
extends
StatelessWidget
{
const
Example
App
({
super
.
key
});
class
NavigationBar
App
extends
StatelessWidget
{
const
NavigationBar
App
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
...
...
examples/api/lib/material/navigation_bar/navigation_bar.1.dart
View file @
f07db401
...
...
@@ -2,366 +2,97 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Flutter code sample for [NavigationBar]
with nested [Navigator] destinations
.
/// Flutter code sample for [NavigationBar].
import
'package:flutter/material.dart'
;
void
main
(
)
{
runApp
(
const
MaterialApp
(
home:
Home
()));
}
class
Home
extends
StatefulWidget
{
const
Home
({
super
.
key
});
@override
State
<
Home
>
createState
()
=>
_HomeState
();
}
class
_HomeState
extends
State
<
Home
>
with
TickerProviderStateMixin
<
Home
>
{
static
const
List
<
Destination
>
allDestinations
=
<
Destination
>[
Destination
(
0
,
'Teal'
,
Icons
.
home
,
Colors
.
teal
),
Destination
(
1
,
'Cyan'
,
Icons
.
business
,
Colors
.
cyan
),
Destination
(
2
,
'Orange'
,
Icons
.
school
,
Colors
.
orange
),
Destination
(
3
,
'Blue'
,
Icons
.
flight
,
Colors
.
blue
),
];
void
main
(
)
=>
runApp
(
const
NavigationBarApp
());
late
final
List
<
GlobalKey
<
NavigatorState
>>
navigatorKeys
;
late
final
List
<
GlobalKey
>
destinationKeys
;
late
final
List
<
AnimationController
>
destinationFaders
;
late
final
List
<
Widget
>
destinationViews
;
int
selectedIndex
=
0
;
AnimationController
buildFaderController
()
{
final
AnimationController
controller
=
AnimationController
(
vsync:
this
,
duration:
const
Duration
(
milliseconds:
200
));
controller
.
addStatusListener
((
AnimationStatus
status
)
{
if
(
status
==
AnimationStatus
.
dismissed
)
{
setState
(()
{
});
// Rebuild unselected destinations offstage.
}
});
return
controller
;
}
@override
void
initState
()
{
super
.
initState
();
navigatorKeys
=
List
<
GlobalKey
<
NavigatorState
>>.
generate
(
allDestinations
.
length
,
(
int
index
)
=>
GlobalKey
()).
toList
();
destinationFaders
=
List
<
AnimationController
>.
generate
(
allDestinations
.
length
,
(
int
index
)
=>
buildFaderController
()).
toList
();
destinationFaders
[
selectedIndex
].
value
=
1.0
;
destinationViews
=
allDestinations
.
map
((
Destination
destination
)
{
return
FadeTransition
(
opacity:
destinationFaders
[
destination
.
index
].
drive
(
CurveTween
(
curve:
Curves
.
fastOutSlowIn
)),
child:
DestinationView
(
destination:
destination
,
navigatorKey:
navigatorKeys
[
destination
.
index
],
)
);
}).
toList
();
}
@override
void
dispose
()
{
for
(
final
AnimationController
controller
in
destinationFaders
)
{
controller
.
dispose
();
}
super
.
dispose
();
}
class
NavigationBarApp
extends
StatelessWidget
{
const
NavigationBarApp
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
return
WillPopScope
(
onWillPop:
()
async
{
final
NavigatorState
navigator
=
navigatorKeys
[
selectedIndex
].
currentState
!;
if
(!
navigator
.
canPop
())
{
return
true
;
}
navigator
.
pop
();
return
false
;
},
child:
Scaffold
(
body:
SafeArea
(
top:
false
,
child:
Stack
(
fit:
StackFit
.
expand
,
children:
allDestinations
.
map
((
Destination
destination
)
{
final
int
index
=
destination
.
index
;
final
Widget
view
=
destinationViews
[
index
];
if
(
index
==
selectedIndex
)
{
destinationFaders
[
index
].
forward
();
return
Offstage
(
offstage:
false
,
child:
view
);
}
else
{
destinationFaders
[
index
].
reverse
();
if
(
destinationFaders
[
index
].
isAnimating
)
{
return
IgnorePointer
(
child:
view
);
}
return
Offstage
(
child:
view
);
}
}).
toList
(),
),
),
bottomNavigationBar:
NavigationBar
(
selectedIndex:
selectedIndex
,
onDestinationSelected:
(
int
index
)
{
setState
(()
{
selectedIndex
=
index
;
});
},
destinations:
allDestinations
.
map
((
Destination
destination
)
{
return
NavigationDestination
(
icon:
Icon
(
destination
.
icon
,
color:
destination
.
color
),
label:
destination
.
title
,
);
}).
toList
(),
),
),
);
return
const
MaterialApp
(
home:
NavigationExample
());
}
}
class
Destination
{
const
Destination
(
this
.
index
,
this
.
title
,
this
.
icon
,
this
.
color
);
final
int
index
;
final
String
title
;
final
IconData
icon
;
final
MaterialColor
color
;
}
class
RootPage
extends
StatelessWidget
{
const
RootPage
({
super
.
key
,
required
this
.
destination
});
class
NavigationExample
extends
StatefulWidget
{
const
NavigationExample
({
super
.
key
});
final
Destination
destination
;
@override
State
<
NavigationExample
>
createState
()
=>
_NavigationExampleState
();
}
Widget
_buildDialog
(
BuildContext
context
)
{
return
AlertDialog
(
title:
Text
(
'
${destination.title}
AlertDialog'
),
actions:
<
Widget
>[
TextButton
(
onPressed:
()
{
Navigator
.
pop
(
context
);
},
child:
const
Text
(
'OK'
),
),
],
);
}
class
_NavigationExampleState
extends
State
<
NavigationExample
>
{
int
currentPageIndex
=
0
;
NavigationDestinationLabelBehavior
labelBehavior
=
NavigationDestinationLabelBehavior
.
alwaysShow
;
@override
Widget
build
(
BuildContext
context
)
{
final
TextStyle
headlineSmall
=
Theme
.
of
(
context
).
textTheme
.
headlineSmall
!;
final
ButtonStyle
buttonStyle
=
ElevatedButton
.
styleFrom
(
backgroundColor:
destination
.
color
,
visualDensity:
VisualDensity
.
comfortable
,
padding:
const
EdgeInsets
.
symmetric
(
vertical:
12
,
horizontal:
16
),
textStyle:
headlineSmall
,
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${destination.title}
RootPage - /'
),
backgroundColor:
destination
.
color
,
bottomNavigationBar:
NavigationBar
(
labelBehavior:
labelBehavior
,
selectedIndex:
currentPageIndex
,
onDestinationSelected:
(
int
index
)
{
setState
(()
{
currentPageIndex
=
index
;
});
},
destinations:
const
<
Widget
>[
NavigationDestination
(
icon:
Icon
(
Icons
.
explore
),
label:
'Explore'
,
),
NavigationDestination
(
icon:
Icon
(
Icons
.
commute
),
label:
'Commute'
,
),
NavigationDestination
(
selectedIcon:
Icon
(
Icons
.
bookmark
),
icon:
Icon
(
Icons
.
bookmark_border
),
label:
'Saved'
,
),
],
),
backgroundColor:
destination
.
color
[
50
],
body:
Center
(
child:
Column
(
mainAxis
Size:
MainAxisSize
.
min
,
mainAxis
Alignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
Navigator
.
pushNamed
(
context
,
'/list'
);
},
child:
const
Text
(
'Push /list'
),
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
showDialog
(
context:
context
,
useRootNavigator:
false
,
builder:
_buildDialog
,
);
},
child:
const
Text
(
'Local Dialog'
),
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
showDialog
(
context:
context
,
useRootNavigator:
true
,
builder:
_buildDialog
,
);
},
child:
const
Text
(
'Root Dialog'
),
),
const
SizedBox
(
height:
16
),
Builder
(
builder:
(
BuildContext
context
)
{
return
ElevatedButton
(
style:
buttonStyle
,
Text
(
'Label behavior:
${labelBehavior.name}
'
),
const
SizedBox
(
height:
10
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
showBottomSheet
(
context:
context
,
builder:
(
BuildContext
context
)
{
return
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
width:
double
.
infinity
,
child:
Text
(
'
${destination.title}
BottomSheet
\n
'
'Tap the back button to dismiss'
,
style:
headlineSmall
,
softWrap:
true
,
textAlign:
TextAlign
.
center
,
),
);
},
);
setState
(()
{
labelBehavior
=
NavigationDestinationLabelBehavior
.
alwaysShow
;
});
},
child:
const
Text
(
'Local BottomSheet'
),
);
},
),
],
),
),
);
}
}
class
ListPage
extends
StatelessWidget
{
const
ListPage
({
super
.
key
,
required
this
.
destination
});
final
Destination
destination
;
@override
Widget
build
(
BuildContext
context
)
{
const
int
itemCount
=
50
;
final
ButtonStyle
buttonStyle
=
OutlinedButton
.
styleFrom
(
foregroundColor:
destination
.
color
,
fixedSize:
const
Size
.
fromHeight
(
128
),
textStyle:
Theme
.
of
(
context
).
textTheme
.
headlineSmall
,
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${destination.title}
ListPage - /list'
),
backgroundColor:
destination
.
color
,
),
backgroundColor:
destination
.
color
[
50
],
body:
SizedBox
.
expand
(
child:
ListView
.
builder
(
itemCount:
itemCount
,
itemBuilder:
(
BuildContext
context
,
int
index
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
4
,
horizontal:
8
),
child:
OutlinedButton
(
style:
buttonStyle
.
copyWith
(
backgroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
.
lerp
(
destination
.
color
[
100
],
Colors
.
white
,
index
/
itemCount
)!
),
child:
const
Text
(
'alwaysShow'
),
),
onPressed:
()
{
Navigator
.
pushNamed
(
context
,
'/text'
);
},
child:
Text
(
'Push /text [
$index
]'
),
),
);
},
),
),
);
}
}
class
TextPage
extends
StatefulWidget
{
const
TextPage
({
super
.
key
,
required
this
.
destination
});
final
Destination
destination
;
@override
State
<
TextPage
>
createState
()
=>
_TextPageState
();
}
class
_TextPageState
extends
State
<
TextPage
>
{
late
final
TextEditingController
textController
;
@override
void
initState
()
{
super
.
initState
();
textController
=
TextEditingController
(
text:
'Sample Text'
);
}
@override
void
dispose
()
{
textController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${widget.destination.title}
TextPage - /list/text'
),
backgroundColor:
widget
.
destination
.
color
,
),
backgroundColor:
widget
.
destination
.
color
[
50
],
body:
Container
(
padding:
const
EdgeInsets
.
all
(
32.0
),
alignment:
Alignment
.
center
,
child:
TextField
(
controller:
textController
,
style:
theme
.
primaryTextTheme
.
headlineMedium
?.
copyWith
(
color:
widget
.
destination
.
color
,
),
decoration:
InputDecoration
(
focusedBorder:
UnderlineInputBorder
(
borderSide:
BorderSide
(
color:
widget
.
destination
.
color
,
width:
3.0
,
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelBehavior
=
NavigationDestinationLabelBehavior
.
onlyShowSelected
;
});
},
child:
const
Text
(
'onlyShowSelected'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelBehavior
=
NavigationDestinationLabelBehavior
.
alwaysHide
;
});
},
child:
const
Text
(
'alwaysHide'
),
),
],
),
)
,
]
,
),
),
);
}
}
class
DestinationView
extends
StatefulWidget
{
const
DestinationView
({
super
.
key
,
required
this
.
destination
,
required
this
.
navigatorKey
,
});
final
Destination
destination
;
final
Key
navigatorKey
;
@override
State
<
DestinationView
>
createState
()
=>
_DestinationViewState
();
}
class
_DestinationViewState
extends
State
<
DestinationView
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Navigator
(
key:
widget
.
navigatorKey
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
MaterialPageRoute
<
void
>(
settings:
settings
,
builder:
(
BuildContext
context
)
{
switch
(
settings
.
name
)
{
case
'/'
:
return
RootPage
(
destination:
widget
.
destination
);
case
'/list'
:
return
ListPage
(
destination:
widget
.
destination
);
case
'/text'
:
return
TextPage
(
destination:
widget
.
destination
);
}
assert
(
false
);
return
const
SizedBox
();
},
);
},
);
}
}
examples/api/lib/material/navigation_bar/navigation_bar.2.dart
0 → 100644
View file @
f07db401
// 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 [NavigationBar] with nested [Navigator] destinations.
import
'package:flutter/material.dart'
;
void
main
(
)
{
runApp
(
const
MaterialApp
(
home:
Home
()));
}
class
Home
extends
StatefulWidget
{
const
Home
({
super
.
key
});
@override
State
<
Home
>
createState
()
=>
_HomeState
();
}
class
_HomeState
extends
State
<
Home
>
with
TickerProviderStateMixin
<
Home
>
{
static
const
List
<
Destination
>
allDestinations
=
<
Destination
>[
Destination
(
0
,
'Teal'
,
Icons
.
home
,
Colors
.
teal
),
Destination
(
1
,
'Cyan'
,
Icons
.
business
,
Colors
.
cyan
),
Destination
(
2
,
'Orange'
,
Icons
.
school
,
Colors
.
orange
),
Destination
(
3
,
'Blue'
,
Icons
.
flight
,
Colors
.
blue
),
];
late
final
List
<
GlobalKey
<
NavigatorState
>>
navigatorKeys
;
late
final
List
<
GlobalKey
>
destinationKeys
;
late
final
List
<
AnimationController
>
destinationFaders
;
late
final
List
<
Widget
>
destinationViews
;
int
selectedIndex
=
0
;
AnimationController
buildFaderController
()
{
final
AnimationController
controller
=
AnimationController
(
vsync:
this
,
duration:
const
Duration
(
milliseconds:
200
));
controller
.
addStatusListener
((
AnimationStatus
status
)
{
if
(
status
==
AnimationStatus
.
dismissed
)
{
setState
(()
{
});
// Rebuild unselected destinations offstage.
}
});
return
controller
;
}
@override
void
initState
()
{
super
.
initState
();
navigatorKeys
=
List
<
GlobalKey
<
NavigatorState
>>.
generate
(
allDestinations
.
length
,
(
int
index
)
=>
GlobalKey
()).
toList
();
destinationFaders
=
List
<
AnimationController
>.
generate
(
allDestinations
.
length
,
(
int
index
)
=>
buildFaderController
()).
toList
();
destinationFaders
[
selectedIndex
].
value
=
1.0
;
destinationViews
=
allDestinations
.
map
((
Destination
destination
)
{
return
FadeTransition
(
opacity:
destinationFaders
[
destination
.
index
].
drive
(
CurveTween
(
curve:
Curves
.
fastOutSlowIn
)),
child:
DestinationView
(
destination:
destination
,
navigatorKey:
navigatorKeys
[
destination
.
index
],
)
);
}).
toList
();
}
@override
void
dispose
()
{
for
(
final
AnimationController
controller
in
destinationFaders
)
{
controller
.
dispose
();
}
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
return
WillPopScope
(
onWillPop:
()
async
{
final
NavigatorState
navigator
=
navigatorKeys
[
selectedIndex
].
currentState
!;
if
(!
navigator
.
canPop
())
{
return
true
;
}
navigator
.
pop
();
return
false
;
},
child:
Scaffold
(
body:
SafeArea
(
top:
false
,
child:
Stack
(
fit:
StackFit
.
expand
,
children:
allDestinations
.
map
((
Destination
destination
)
{
final
int
index
=
destination
.
index
;
final
Widget
view
=
destinationViews
[
index
];
if
(
index
==
selectedIndex
)
{
destinationFaders
[
index
].
forward
();
return
Offstage
(
offstage:
false
,
child:
view
);
}
else
{
destinationFaders
[
index
].
reverse
();
if
(
destinationFaders
[
index
].
isAnimating
)
{
return
IgnorePointer
(
child:
view
);
}
return
Offstage
(
child:
view
);
}
}).
toList
(),
),
),
bottomNavigationBar:
NavigationBar
(
selectedIndex:
selectedIndex
,
onDestinationSelected:
(
int
index
)
{
setState
(()
{
selectedIndex
=
index
;
});
},
destinations:
allDestinations
.
map
((
Destination
destination
)
{
return
NavigationDestination
(
icon:
Icon
(
destination
.
icon
,
color:
destination
.
color
),
label:
destination
.
title
,
);
}).
toList
(),
),
),
);
}
}
class
Destination
{
const
Destination
(
this
.
index
,
this
.
title
,
this
.
icon
,
this
.
color
);
final
int
index
;
final
String
title
;
final
IconData
icon
;
final
MaterialColor
color
;
}
class
RootPage
extends
StatelessWidget
{
const
RootPage
({
super
.
key
,
required
this
.
destination
});
final
Destination
destination
;
Widget
_buildDialog
(
BuildContext
context
)
{
return
AlertDialog
(
title:
Text
(
'
${destination.title}
AlertDialog'
),
actions:
<
Widget
>[
TextButton
(
onPressed:
()
{
Navigator
.
pop
(
context
);
},
child:
const
Text
(
'OK'
),
),
],
);
}
@override
Widget
build
(
BuildContext
context
)
{
final
TextStyle
headlineSmall
=
Theme
.
of
(
context
).
textTheme
.
headlineSmall
!;
final
ButtonStyle
buttonStyle
=
ElevatedButton
.
styleFrom
(
backgroundColor:
destination
.
color
,
visualDensity:
VisualDensity
.
comfortable
,
padding:
const
EdgeInsets
.
symmetric
(
vertical:
12
,
horizontal:
16
),
textStyle:
headlineSmall
,
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${destination.title}
RootPage - /'
),
backgroundColor:
destination
.
color
,
),
backgroundColor:
destination
.
color
[
50
],
body:
Center
(
child:
Column
(
mainAxisSize:
MainAxisSize
.
min
,
children:
<
Widget
>[
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
Navigator
.
pushNamed
(
context
,
'/list'
);
},
child:
const
Text
(
'Push /list'
),
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
showDialog
(
context:
context
,
useRootNavigator:
false
,
builder:
_buildDialog
,
);
},
child:
const
Text
(
'Local Dialog'
),
),
const
SizedBox
(
height:
16
),
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
showDialog
(
context:
context
,
useRootNavigator:
true
,
builder:
_buildDialog
,
);
},
child:
const
Text
(
'Root Dialog'
),
),
const
SizedBox
(
height:
16
),
Builder
(
builder:
(
BuildContext
context
)
{
return
ElevatedButton
(
style:
buttonStyle
,
onPressed:
()
{
showBottomSheet
(
context:
context
,
builder:
(
BuildContext
context
)
{
return
Container
(
padding:
const
EdgeInsets
.
all
(
16
),
width:
double
.
infinity
,
child:
Text
(
'
${destination.title}
BottomSheet
\n
'
'Tap the back button to dismiss'
,
style:
headlineSmall
,
softWrap:
true
,
textAlign:
TextAlign
.
center
,
),
);
},
);
},
child:
const
Text
(
'Local BottomSheet'
),
);
},
),
],
),
),
);
}
}
class
ListPage
extends
StatelessWidget
{
const
ListPage
({
super
.
key
,
required
this
.
destination
});
final
Destination
destination
;
@override
Widget
build
(
BuildContext
context
)
{
const
int
itemCount
=
50
;
final
ButtonStyle
buttonStyle
=
OutlinedButton
.
styleFrom
(
foregroundColor:
destination
.
color
,
fixedSize:
const
Size
.
fromHeight
(
128
),
textStyle:
Theme
.
of
(
context
).
textTheme
.
headlineSmall
,
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${destination.title}
ListPage - /list'
),
backgroundColor:
destination
.
color
,
),
backgroundColor:
destination
.
color
[
50
],
body:
SizedBox
.
expand
(
child:
ListView
.
builder
(
itemCount:
itemCount
,
itemBuilder:
(
BuildContext
context
,
int
index
)
{
return
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
4
,
horizontal:
8
),
child:
OutlinedButton
(
style:
buttonStyle
.
copyWith
(
backgroundColor:
MaterialStatePropertyAll
<
Color
>(
Color
.
lerp
(
destination
.
color
[
100
],
Colors
.
white
,
index
/
itemCount
)!
),
),
onPressed:
()
{
Navigator
.
pushNamed
(
context
,
'/text'
);
},
child:
Text
(
'Push /text [
$index
]'
),
),
);
},
),
),
);
}
}
class
TextPage
extends
StatefulWidget
{
const
TextPage
({
super
.
key
,
required
this
.
destination
});
final
Destination
destination
;
@override
State
<
TextPage
>
createState
()
=>
_TextPageState
();
}
class
_TextPageState
extends
State
<
TextPage
>
{
late
final
TextEditingController
textController
;
@override
void
initState
()
{
super
.
initState
();
textController
=
TextEditingController
(
text:
'Sample Text'
);
}
@override
void
dispose
()
{
textController
.
dispose
();
super
.
dispose
();
}
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
return
Scaffold
(
appBar:
AppBar
(
title:
Text
(
'
${widget.destination.title}
TextPage - /list/text'
),
backgroundColor:
widget
.
destination
.
color
,
),
backgroundColor:
widget
.
destination
.
color
[
50
],
body:
Container
(
padding:
const
EdgeInsets
.
all
(
32.0
),
alignment:
Alignment
.
center
,
child:
TextField
(
controller:
textController
,
style:
theme
.
primaryTextTheme
.
headlineMedium
?.
copyWith
(
color:
widget
.
destination
.
color
,
),
decoration:
InputDecoration
(
focusedBorder:
UnderlineInputBorder
(
borderSide:
BorderSide
(
color:
widget
.
destination
.
color
,
width:
3.0
,
),
),
),
),
),
);
}
}
class
DestinationView
extends
StatefulWidget
{
const
DestinationView
({
super
.
key
,
required
this
.
destination
,
required
this
.
navigatorKey
,
});
final
Destination
destination
;
final
Key
navigatorKey
;
@override
State
<
DestinationView
>
createState
()
=>
_DestinationViewState
();
}
class
_DestinationViewState
extends
State
<
DestinationView
>
{
@override
Widget
build
(
BuildContext
context
)
{
return
Navigator
(
key:
widget
.
navigatorKey
,
onGenerateRoute:
(
RouteSettings
settings
)
{
return
MaterialPageRoute
<
void
>(
settings:
settings
,
builder:
(
BuildContext
context
)
{
switch
(
settings
.
name
)
{
case
'/'
:
return
RootPage
(
destination:
widget
.
destination
);
case
'/list'
:
return
ListPage
(
destination:
widget
.
destination
);
case
'/text'
:
return
TextPage
(
destination:
widget
.
destination
);
}
assert
(
false
);
return
const
SizedBox
();
},
);
},
);
}
}
examples/api/test/material/navigation_bar/navigation_bar.0_test.dart
View file @
f07db401
...
...
@@ -11,10 +11,9 @@ void main() {
testWidgets
(
'Navigation bar updates destination on tap'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
Example
App
(),
const
example
.
NavigationBar
App
(),
);
final
NavigationBar
navigationBarWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationBar
));
final
NavigationBar
navigationBarWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationBar
));
/// NavigationDestinations must be rendered
expect
(
find
.
text
(
'Explore'
),
findsOneWidget
);
...
...
examples/api/test/material/navigation_bar/navigation_bar.1_test.dart
View file @
f07db401
...
...
@@ -3,106 +3,41 @@
// found in the LICENSE file.
import
'package:flutter/material.dart'
;
import
'package:flutter_api_samples/material/navigation_bar/navigation_bar.1.dart'
as
example
;
import
'package:flutter_api_samples/material/navigation_bar/navigation_bar.1.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'RootPage: only selected destination is on stage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
testWidgets
(
'Navigation bar updates label behavior when tapping buttons'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
NavigationBarApp
(),
);
NavigationBar
navigationBarWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationBar
));
const
String
tealTitle
=
'Teal RootPage - /'
;
const
String
cyanTitle
=
'Cyan RootPage - /'
;
const
String
orangeTitle
=
'Orange RootPage - /'
;
const
String
blueTitle
=
'Blue RootPage - /'
;
expect
(
find
.
text
(
'Label behavior: alwaysShow'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
/// Test alwaysShow label behavior button.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'alwaysShow'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsOneWidget
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Cyan'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsOneWidget
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Orange'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsOneWidget
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Blue'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsOneWidget
);
});
testWidgets
(
'RootPage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
text
(
'Local Dialog'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
text
(
'OK'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsNothing
);
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
text
(
'Root Dialog'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsOneWidget
);
await
tester
.
tapAt
(
const
Offset
(
5
,
5
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsNothing
);
await
tester
.
tap
(
find
.
text
(
'Local BottomSheet'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
BottomSheet
),
findsOneWidget
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
BottomSheet
),
findsNothing
);
await
tester
.
tap
(
find
.
text
(
'Push /list'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
});
expect
(
find
.
text
(
'Label behavior: alwaysShow'
),
findsOneWidget
);
expect
(
navigationBarWidget
.
labelBehavior
,
NavigationDestinationLabelBehavior
.
alwaysShow
);
testWidgets
(
'ListPage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
expect
(
find
.
text
(
'Teal RootPage - /'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Push /list'
));
/// Test onlyShowSelected label behavior button.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'onlyShowSelected'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
expect
(
find
.
text
(
'Push /text [0]'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Orange'
));
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Push /list'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Orange ListPage - /list'
),
findsOneWidget
);
expect
(
find
.
text
(
'Push /text [0]'
),
findsOneWidget
);
expect
(
find
.
text
(
'Label behavior: onlyShowSelected'
),
findsOneWidget
);
navigationBarWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationBar
));
expect
(
navigationBarWidget
.
labelBehavior
,
NavigationDestinationLabelBehavior
.
onlyShowSelected
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
/// Test alwaysHide label behavior button.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'alwaysHide'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Orange RootPage - /'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal RootPage - /'
),
findsOneWidget
);
expect
(
find
.
text
(
'Label behavior: alwaysHide'
),
findsOneWidget
);
navigationBarWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationBar
));
expect
(
navigationBarWidget
.
labelBehavior
,
NavigationDestinationLabelBehavior
.
alwaysHide
);
});
}
examples/api/test/material/navigation_bar/navigation_bar.2_test.dart
0 → 100644
View file @
f07db401
// 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/navigation_bar/navigation_bar.2.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'RootPage: only selected destination is on stage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
const
String
tealTitle
=
'Teal RootPage - /'
;
const
String
cyanTitle
=
'Cyan RootPage - /'
;
const
String
orangeTitle
=
'Orange RootPage - /'
;
const
String
blueTitle
=
'Blue RootPage - /'
;
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsOneWidget
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Cyan'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsOneWidget
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Orange'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsOneWidget
);
expect
(
find
.
text
(
blueTitle
),
findsNothing
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Blue'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
tealTitle
),
findsNothing
);
expect
(
find
.
text
(
cyanTitle
),
findsNothing
);
expect
(
find
.
text
(
orangeTitle
),
findsNothing
);
expect
(
find
.
text
(
blueTitle
),
findsOneWidget
);
});
testWidgets
(
'RootPage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
text
(
'Local Dialog'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
text
(
'OK'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsNothing
);
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
text
(
'Root Dialog'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsOneWidget
);
await
tester
.
tapAt
(
const
Offset
(
5
,
5
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal AlertDialog'
),
findsNothing
);
await
tester
.
tap
(
find
.
text
(
'Local BottomSheet'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
BottomSheet
),
findsOneWidget
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
BottomSheet
),
findsNothing
);
await
tester
.
tap
(
find
.
text
(
'Push /list'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
});
testWidgets
(
'ListPage'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
MaterialApp
(
home:
example
.
Home
()));
expect
(
find
.
text
(
'Teal RootPage - /'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Push /list'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
expect
(
find
.
text
(
'Push /text [0]'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Orange'
));
await
tester
.
pumpAndSettle
();
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Push /list'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Orange ListPage - /list'
),
findsOneWidget
);
expect
(
find
.
text
(
'Push /text [0]'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Orange RootPage - /'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
widgetWithText
(
NavigationDestination
,
'Teal'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal ListPage - /list'
),
findsOneWidget
);
await
tester
.
tap
(
find
.
byType
(
BackButton
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Teal RootPage - /'
),
findsOneWidget
);
});
}
packages/flutter/lib/src/material/navigation_bar.dart
View file @
f07db401
...
...
@@ -53,6 +53,14 @@ const double _kIndicatorWidth = 64;
/// {@end-tool}
///
/// {@tool dartpad}
/// This example showcases [NavigationBar] label behaviors. When tapping on one
/// of the label behavior options, the [labelBehavior] of the [NavigationBar]
/// will be updated.
///
/// ** See code in examples/api/lib/material/navigation_bar/navigation_bar.1.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows a [NavigationBar] as it is used within a [Scaffold]
/// widget when there are nested navigators that provide local navigation. The
/// [NavigationBar] has four [NavigationDestination] widgets with different
...
...
@@ -60,7 +68,7 @@ const double _kIndicatorWidth = 64;
/// item's index and displays a corresponding page with its own local navigator
/// in the body of a [Scaffold].
///
/// ** See code in examples/api/lib/material/navigation_bar/navigation_bar.
1
.dart **
/// ** See code in examples/api/lib/material/navigation_bar/navigation_bar.
2
.dart **
/// {@end-tool}
/// See also:
///
...
...
@@ -266,6 +274,8 @@ class NavigationDestination extends StatelessWidget {
super
.
key
,
required
this
.
icon
,
this
.
selectedIcon
,
this
.
indicatorColor
,
this
.
indicatorShape
,
required
this
.
label
,
this
.
tooltip
,
});
...
...
@@ -290,6 +300,12 @@ class NavigationDestination extends StatelessWidget {
/// would use a size of 24.0 and [ColorScheme.onSurface].
final
Widget
?
selectedIcon
;
/// The color of the [indicatorShape] when this destination is selected.
final
Color
?
indicatorColor
;
/// The shape of the selected inidicator.
final
ShapeBorder
?
indicatorShape
;
/// The text label that appears below the icon of this
/// [NavigationDestination].
///
...
...
@@ -335,8 +351,8 @@ class NavigationDestination extends StatelessWidget {
children:
<
Widget
>[
NavigationIndicator
(
animation:
animation
,
color:
navigationBarTheme
.
indicatorColor
??
defaults
.
indicatorColor
!,
shape:
navigationBarTheme
.
indicatorShape
??
defaults
.
indicatorShape
!
color:
indicatorColor
??
navigationBarTheme
.
indicatorColor
??
defaults
.
indicatorColor
!,
shape:
indicatorShape
??
navigationBarTheme
.
indicatorShape
??
defaults
.
indicatorShape
!
),
_StatusTransitionWidgetBuilder
(
animation:
animation
,
...
...
@@ -440,10 +456,10 @@ class _NavigationDestinationBuilder extends StatelessWidget {
final
double
labelPadding
;
switch
(
info
.
labelBehavior
)
{
case
NavigationDestinationLabelBehavior
.
alwaysShow
:
labelPadding
=
10
;
labelPadding
=
8
;
break
;
case
NavigationDestinationLabelBehavior
.
onlyShowSelected
:
labelPadding
=
selected
?
10
:
0
;
labelPadding
=
selected
?
8
:
0
;
break
;
case
NavigationDestinationLabelBehavior
.
alwaysHide
:
labelPadding
=
0
;
...
...
packages/flutter/test/material/navigation_bar_test.dart
View file @
f07db401
...
...
@@ -589,7 +589,7 @@ void main() {
await
tester
.
pumpAndSettle
();
final
RenderObject
inkFeatures
=
tester
.
allRenderObjects
.
firstWhere
((
RenderObject
object
)
=>
object
.
runtimeType
.
toString
()
==
'_RenderInkFeatures'
);
Offset
indicatorCenter
=
const
Offset
(
600
,
3
0
);
Offset
indicatorCenter
=
const
Offset
(
600
,
3
2
);
const
Size
includedIndicatorSize
=
Size
(
64
,
32
);
const
Size
excludedIndicatorSize
=
Size
(
74
,
40
);
...
...
@@ -715,7 +715,7 @@ void main() {
selectedIndex
=
1
;
await
tester
.
pumpWidget
(
buildWidget
(
labelBehavior:
NavigationDestinationLabelBehavior
.
onlyShowSelected
));
await
tester
.
pumpAndSettle
();
indicatorCenter
=
const
Offset
(
600
,
3
0
);
indicatorCenter
=
const
Offset
(
600
,
3
2
);
expect
(
inkFeatures
,
...
...
@@ -803,6 +803,96 @@ void main() {
transform
=
tester
.
widget
<
Transform
>(
transformFinder
).
transform
;
expect
(
transform
.
getColumn
(
0
)[
0
],
1.0
);
});
testWidgets
(
'Navigation destination updates indicator color and shape'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
true
);
const
Color
color
=
Color
(
0xff0000ff
);
const
ShapeBorder
shape
=
CircleBorder
();
Widget
buildNaviagationBar
({
Color
?
indicatorColor
,
ShapeBorder
?
indicatorShape
})
{
return
MaterialApp
(
theme:
theme
,
home:
Scaffold
(
bottomNavigationBar:
NavigationBar
(
destinations:
<
Widget
>[
NavigationDestination
(
icon:
const
Icon
(
Icons
.
ac_unit
),
label:
'AC'
,
indicatorColor:
indicatorColor
,
indicatorShape:
indicatorShape
,
),
const
NavigationDestination
(
icon:
Icon
(
Icons
.
access_alarm
),
label:
'Alarm'
,
),
],
onDestinationSelected:
(
int
i
)
{
},
),
),
);
}
await
tester
.
pumpWidget
(
buildNaviagationBar
());
// Test default indicator color and shape.
expect
(
_indicator
(
tester
)?.
color
,
theme
.
colorScheme
.
secondaryContainer
);
expect
(
_indicator
(
tester
)?.
shape
,
const
StadiumBorder
());
await
tester
.
pumpWidget
(
buildNaviagationBar
(
indicatorColor:
color
,
indicatorShape:
shape
));
// Test custom indicator color and shape.
expect
(
_indicator
(
tester
)?.
color
,
color
);
expect
(
_indicator
(
tester
)?.
shape
,
shape
);
});
group
(
'Material 2'
,
()
{
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
// is turned on by default, these tests can be removed.
testWidgets
(
'Navigation destination updates indicator color and shape'
,
(
WidgetTester
tester
)
async
{
final
ThemeData
theme
=
ThemeData
(
useMaterial3:
false
);
const
Color
color
=
Color
(
0xff0000ff
);
const
ShapeBorder
shape
=
CircleBorder
();
Widget
buildNaviagationBar
({
Color
?
indicatorColor
,
ShapeBorder
?
indicatorShape
})
{
return
MaterialApp
(
theme:
theme
,
home:
Scaffold
(
bottomNavigationBar:
NavigationBar
(
destinations:
<
Widget
>[
NavigationDestination
(
icon:
const
Icon
(
Icons
.
ac_unit
),
label:
'AC'
,
indicatorColor:
indicatorColor
,
indicatorShape:
indicatorShape
,
),
const
NavigationDestination
(
icon:
Icon
(
Icons
.
access_alarm
),
label:
'Alarm'
,
),
],
onDestinationSelected:
(
int
i
)
{
},
),
),
);
}
await
tester
.
pumpWidget
(
buildNaviagationBar
());
// Test default indicator color and shape.
expect
(
_indicator
(
tester
)?.
color
,
theme
.
colorScheme
.
secondary
.
withOpacity
(
0.24
));
expect
(
_indicator
(
tester
)?.
shape
,
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
16
))),
);
await
tester
.
pumpWidget
(
buildNaviagationBar
(
indicatorColor:
color
,
indicatorShape:
shape
));
// Test custom indicator color and shape.
expect
(
_indicator
(
tester
)?.
color
,
color
);
expect
(
_indicator
(
tester
)?.
shape
,
shape
);
});
});
}
Widget
_buildWidget
(
Widget
child
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment