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
eca09252
Unverified
Commit
eca09252
authored
Apr 18, 2022
by
Taha Tesser
Committed by
GitHub
Apr 18, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Material 3 `NavigationRail` example and improve Material 2 example (#101345)
parent
3c4d7a1a
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
512 additions
and
20 deletions
+512
-20
navigation_rail.0.dart
...s/api/lib/material/navigation_rail/navigation_rail.0.dart
+117
-13
navigation_rail.1.dart
...s/api/lib/material/navigation_rail/navigation_rail.1.dart
+184
-0
navigation_rail.extended_animation.0.dart
...navigation_rail/navigation_rail.extended_animation.0.dart
+10
-7
navigation_rail.0_test.dart
...test/material/navigation_rail/navigation_rail.0_test.dart
+97
-0
navigation_rail.1_test.dart
...test/material/navigation_rail/navigation_rail.1_test.dart
+97
-0
navigation_rail.dart
packages/flutter/lib/src/material/navigation_rail.dart
+7
-0
No files found.
examples/api/lib/material/navigation_rail/navigation_rail.0.dart
View file @
eca09252
...
...
@@ -11,26 +11,27 @@ void main() => runApp(const MyApp());
class
MyApp
extends
StatelessWidget
{
const
MyApp
({
Key
?
key
})
:
super
(
key:
key
);
static
const
String
_title
=
'Flutter Code Sample'
;
@override
Widget
build
(
BuildContext
context
)
{
return
const
MaterialApp
(
title:
_title
,
home:
MyStatefulWidget
(),
home:
NavRailExample
(),
);
}
}
class
MyStatefulWidget
extends
StatefulWidget
{
const
MyStatefulWidget
({
Key
?
key
})
:
super
(
key:
key
);
class
NavRailExample
extends
StatefulWidget
{
const
NavRailExample
({
Key
?
key
})
:
super
(
key:
key
);
@override
State
<
MyStatefulWidget
>
createState
()
=>
_MyStatefulWidget
State
();
State
<
NavRailExample
>
createState
()
=>
_NavRailExample
State
();
}
class
_
MyStatefulWidgetState
extends
State
<
MyStatefulWidget
>
{
class
_
NavRailExampleState
extends
State
<
NavRailExample
>
{
int
_selectedIndex
=
0
;
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
bool
showLeading
=
false
;
bool
showTrailing
=
false
;
double
groupAligment
=
-
1.0
;
@override
Widget
build
(
BuildContext
context
)
{
...
...
@@ -39,12 +40,26 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
children:
<
Widget
>[
NavigationRail
(
selectedIndex:
_selectedIndex
,
groupAlignment:
groupAligment
,
onDestinationSelected:
(
int
index
)
{
setState
(()
{
_selectedIndex
=
index
;
});
},
labelType:
NavigationRailLabelType
.
selected
,
labelType:
labelType
,
leading:
showLeading
?
FloatingActionButton
(
elevation:
0
,
onPressed:
()
{
// Add your onPressed code here!
},
child:
const
Icon
(
Icons
.
add
),
)
:
const
SizedBox
(),
trailing:
showTrailing
?
IconButton
(
onPressed:
()
{
// Add your onPressed code here!
},
icon:
const
Icon
(
Icons
.
more_horiz_rounded
),
)
:
const
SizedBox
(),
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
...
...
@@ -65,11 +80,100 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
),
const
VerticalDivider
(
thickness:
1
,
width:
1
),
// This is the main content.
Expanded
(
child:
Center
(
child:
Text
(
'selectedIndex:
$_selectedIndex
'
),
Expanded
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
Text
(
'selectedIndex:
$_selectedIndex
'
),
const
SizedBox
(
height:
20
),
Text
(
'Label type:
${labelType.name}
'
),
const
SizedBox
(
height:
10
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
none
;
});
},
child:
const
Text
(
'None'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
selected
;
});
},
child:
const
Text
(
'Selected'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
all
;
});
},
child:
const
Text
(
'All'
),
),
],
),
const
SizedBox
(
height:
20
),
Text
(
'Group alignment:
$groupAligment
'
),
const
SizedBox
(
height:
10
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
-
1.0
;
});
},
child:
const
Text
(
'Top'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
0.0
;
});
},
child:
const
Text
(
'Center'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
1.0
;
});
},
child:
const
Text
(
'Bottom'
),
),
],
),
const
SizedBox
(
height:
20
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
showLeading
=
!
showLeading
;
});
},
child:
Text
(
showLeading
?
'Hide Leading'
:
'Show Leading'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
showTrailing
=
!
showTrailing
;
});
},
child:
Text
(
showTrailing
?
'Hide Trailing'
:
'Show Trailing'
),
),
],
),
],
),
),
)
],
),
);
...
...
examples/api/lib/material/navigation_rail/navigation_rail.1.dart
0 → 100644
View file @
eca09252
// 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 NavigationRail
import
'package:flutter/material.dart'
;
void
main
(
)
=>
runApp
(
const
MyApp
());
class
MyApp
extends
StatelessWidget
{
const
MyApp
({
Key
?
key
})
:
super
(
key:
key
);
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
theme:
ThemeData
(
colorSchemeSeed:
const
Color
(
0xff6750a4
),
useMaterial3:
true
),
home:
const
NavRailExample
(),
);
}
}
class
NavRailExample
extends
StatefulWidget
{
const
NavRailExample
({
Key
?
key
})
:
super
(
key:
key
);
@override
State
<
NavRailExample
>
createState
()
=>
_NavRailExampleState
();
}
class
_NavRailExampleState
extends
State
<
NavRailExample
>
{
int
_selectedIndex
=
0
;
NavigationRailLabelType
labelType
=
NavigationRailLabelType
.
all
;
bool
showLeading
=
false
;
bool
showTrailing
=
false
;
double
groupAligment
=
-
1.0
;
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
body:
SafeArea
(
child:
Row
(
children:
<
Widget
>[
NavigationRail
(
selectedIndex:
_selectedIndex
,
groupAlignment:
groupAligment
,
onDestinationSelected:
(
int
index
)
{
setState
(()
{
_selectedIndex
=
index
;
});
},
labelType:
labelType
,
leading:
showLeading
?
FloatingActionButton
(
elevation:
0
,
onPressed:
()
{
// Add your onPressed code here!
},
child:
const
Icon
(
Icons
.
add
),
)
:
const
SizedBox
(),
trailing:
showTrailing
?
IconButton
(
onPressed:
()
{
// Add your onPressed code here!
},
icon:
const
Icon
(
Icons
.
more_horiz_rounded
),
)
:
const
SizedBox
(),
destinations:
const
<
NavigationRailDestination
>[
NavigationRailDestination
(
icon:
Icon
(
Icons
.
favorite_border
),
selectedIcon:
Icon
(
Icons
.
favorite
),
label:
Text
(
'First'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
bookmark_border
),
selectedIcon:
Icon
(
Icons
.
book
),
label:
Text
(
'Second'
),
),
NavigationRailDestination
(
icon:
Icon
(
Icons
.
star_border
),
selectedIcon:
Icon
(
Icons
.
star
),
label:
Text
(
'Third'
),
),
],
),
const
VerticalDivider
(
thickness:
1
,
width:
1
),
// This is the main content.
Expanded
(
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
Text
(
'selectedIndex:
$_selectedIndex
'
),
const
SizedBox
(
height:
20
),
Text
(
'Label type:
${labelType.name}
'
),
const
SizedBox
(
height:
10
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
none
;
});
},
child:
const
Text
(
'None'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
selected
;
});
},
child:
const
Text
(
'Selected'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
labelType
=
NavigationRailLabelType
.
all
;
});
},
child:
const
Text
(
'All'
),
),
],
),
const
SizedBox
(
height:
20
),
Text
(
'Group alignment:
$groupAligment
'
),
const
SizedBox
(
height:
10
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
-
1.0
;
});
},
child:
const
Text
(
'Top'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
0.0
;
});
},
child:
const
Text
(
'Center'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
groupAligment
=
1.0
;
});
},
child:
const
Text
(
'Bottom'
),
),
],
),
const
SizedBox
(
height:
20
),
OverflowBar
(
spacing:
10.0
,
children:
<
Widget
>[
ElevatedButton
(
onPressed:
()
{
setState
(()
{
showLeading
=
!
showLeading
;
});
},
child:
Text
(
showLeading
?
'Hide Leading'
:
'Show Leading'
),
),
ElevatedButton
(
onPressed:
()
{
setState
(()
{
showTrailing
=
!
showTrailing
;
});
},
child:
Text
(
showTrailing
?
'Hide Trailing'
:
'Show Trailing'
),
),
],
),
],
),
),
],
),
),
);
}
}
examples/api/lib/material/navigation_rail/navigation_rail.extended_animation.0.dart
View file @
eca09252
...
...
@@ -13,15 +13,11 @@ void main() => runApp(const MyApp());
class
MyApp
extends
StatelessWidget
{
const
MyApp
({
Key
?
key
})
:
super
(
key:
key
);
static
const
String
_title
=
'NavigationRail.extendedAnimation Sample'
;
@override
Widget
build
(
BuildContext
context
)
{
return
MaterialApp
(
title:
_title
,
return
const
MaterialApp
(
home:
Scaffold
(
appBar:
AppBar
(
title:
const
Text
(
_title
)),
body:
const
MyNavigationRail
(),
body:
MyNavigationRail
(),
),
);
}
...
...
@@ -78,7 +74,14 @@ class _MyNavigationRailState extends State<MyNavigationRail> {
// This is the main content.
Expanded
(
child:
Center
(
child:
Text
(
'selectedIndex:
$_selectedIndex
'
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
const
Text
(
'Tap on FloatingActionButton to expand'
),
const
SizedBox
(
height:
20
),
Text
(
'selectedIndex:
$_selectedIndex
'
),
],
),
),
)
],
...
...
examples/api/test/material/navigation_rail/navigation_rail.0_test.dart
0 → 100644
View file @
eca09252
// 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_rail/navigation_rail.0.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Navigation rail updates destination on tap'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
final
NavigationRail
navigationRailWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationRail
));
/// NavigationRailDestinations must be rendered
expect
(
find
.
text
(
'First'
),
findsOneWidget
);
expect
(
find
.
text
(
'Second'
),
findsOneWidget
);
expect
(
find
.
text
(
'Third'
),
findsOneWidget
);
/// initial index must be zero
expect
(
navigationRailWidget
.
selectedIndex
,
0
);
/// switch to second tab
await
tester
.
tap
(
find
.
text
(
'Second'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'selectedIndex: 1'
),
findsOneWidget
);
/// switch to third tab
await
tester
.
tap
(
find
.
text
(
'Third'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'selectedIndex: 2'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail updates label type'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// initial label type set to all.
expect
(
find
.
text
(
'Label type: all'
),
findsOneWidget
);
// switch to selected label type
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Selected'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Label type: selected'
),
findsOneWidget
);
// switch to none label type
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'None'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Label type: none'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail updates group alignment'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// initial group alignment set top top.
expect
(
find
.
text
(
'Group alignment: -1.0'
),
findsOneWidget
);
// switch to center alignment
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Center'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Group alignment: 0.0'
),
findsOneWidget
);
// switch to bottom alignment
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Bottom'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Group alignment: 1.0'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail shows leading/trailing widgets'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// Initially leading/trailing widgets are hidden.
expect
(
find
.
byType
(
FloatingActionButton
),
findsNothing
);
expect
(
find
.
byType
(
IconButton
),
findsNothing
);
// Tap to show leading Widget.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Show Leading'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
FloatingActionButton
),
findsOneWidget
);
expect
(
find
.
byType
(
IconButton
),
findsNothing
);
// Tap to show trailing Widget.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Show Trailing'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
FloatingActionButton
),
findsOneWidget
);
expect
(
find
.
byType
(
IconButton
),
findsOneWidget
);
});
}
examples/api/test/material/navigation_rail/navigation_rail.1_test.dart
0 → 100644
View file @
eca09252
// 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_rail/navigation_rail.1.dart'
as
example
;
import
'package:flutter_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'Navigation rail updates destination on tap'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
final
NavigationRail
navigationRailWidget
=
tester
.
firstWidget
(
find
.
byType
(
NavigationRail
));
/// NavigationRailDestinations must be rendered
expect
(
find
.
text
(
'First'
),
findsOneWidget
);
expect
(
find
.
text
(
'Second'
),
findsOneWidget
);
expect
(
find
.
text
(
'Third'
),
findsOneWidget
);
/// initial index must be zero
expect
(
navigationRailWidget
.
selectedIndex
,
0
);
/// switch to second tab
await
tester
.
tap
(
find
.
text
(
'Second'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'selectedIndex: 1'
),
findsOneWidget
);
/// switch to third tab
await
tester
.
tap
(
find
.
text
(
'Third'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'selectedIndex: 2'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail updates label type'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// initial label type set to all.
expect
(
find
.
text
(
'Label type: all'
),
findsOneWidget
);
// switch to selected label type
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Selected'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Label type: selected'
),
findsOneWidget
);
// switch to none label type
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'None'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Label type: none'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail updates group alignment'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// initial group alignment set top top.
expect
(
find
.
text
(
'Group alignment: -1.0'
),
findsOneWidget
);
// switch to center alignment
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Center'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Group alignment: 0.0'
),
findsOneWidget
);
// switch to bottom alignment
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Bottom'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
'Group alignment: 1.0'
),
findsOneWidget
);
});
testWidgets
(
'Navigation rail shows leading/trailing widgets'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
const
example
.
MyApp
(),
);
// Initially leading/trailing widgets are hidden.
expect
(
find
.
byType
(
FloatingActionButton
),
findsNothing
);
expect
(
find
.
byType
(
IconButton
),
findsNothing
);
// Tap to show leading Widget.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Show Leading'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
FloatingActionButton
),
findsOneWidget
);
expect
(
find
.
byType
(
IconButton
),
findsNothing
);
// Tap to show trailing Widget.
await
tester
.
tap
(
find
.
widgetWithText
(
ElevatedButton
,
'Show Trailing'
));
await
tester
.
pumpAndSettle
();
expect
(
find
.
byType
(
FloatingActionButton
),
findsOneWidget
);
expect
(
find
.
byType
(
IconButton
),
findsOneWidget
);
});
}
packages/flutter/lib/src/material/navigation_rail.dart
View file @
eca09252
...
...
@@ -46,6 +46,13 @@ import 'theme.dart';
/// ** See code in examples/api/lib/material/navigation_rail/navigation_rail.0.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This sample shows the creation of [NavigationRail] widget used within a Scaffold with 3
/// [NavigationRailDestination]s, as described in: https://m3.material.io/components/navigation-rail/overview
///
/// ** See code in examples/api/lib/material/navigation_rail/navigation_rail.1.dart **
/// {@end-tool}
///
/// See also:
///
/// * [Scaffold], which can display the navigation rail within a [Row] of the
...
...
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