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
3a6530d5
Commit
3a6530d5
authored
Sep 22, 2016
by
Dragoș Tiselice
Committed by
GitHub
Sep 22, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added bottom navigation. (#5877)
parent
d3f540d4
Changes
5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
775 additions
and
8 deletions
+775
-8
material.dart
packages/flutter/lib/material.dart
+1
-0
bottom_navigation_bar.dart
packages/flutter/lib/src/material/bottom_navigation_bar.dart
+569
-0
constants.dart
packages/flutter/lib/src/material/constants.dart
+3
-0
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+35
-8
bottom_navigation_bar_test.dart
...ges/flutter/test/material/bottom_navigation_bar_test.dart
+167
-0
No files found.
packages/flutter/lib/material.dart
View file @
3a6530d5
...
...
@@ -15,6 +15,7 @@ export 'src/material/about.dart';
export
'src/material/app.dart'
;
export
'src/material/app_bar.dart'
;
export
'src/material/arc.dart'
;
export
'src/material/bottom_navigation_bar.dart'
;
export
'src/material/bottom_sheet.dart'
;
export
'src/material/button.dart'
;
export
'src/material/button_bar.dart'
;
...
...
packages/flutter/lib/src/material/bottom_navigation_bar.dart
0 → 100644
View file @
3a6530d5
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/constants.dart
View file @
3a6530d5
...
...
@@ -5,6 +5,9 @@
/// The height of the toolbar component of the [AppBar].
const
double
kToolbarHeight
=
56.0
;
/// The height of the bottom navigation bar.
const
double
kBottomNavigationBarHeight
=
60.0
;
/// The height of a tab bar containing text.
const
double
kTextTabBarHeight
=
48.0
;
...
...
packages/flutter/lib/src/material/scaffold.dart
View file @
3a6530d5
...
...
@@ -53,6 +53,7 @@ enum _ScaffoldSlot {
appBar
,
bottomSheet
,
snackBar
,
bottomNavigationBar
,
floatingActionButton
,
drawer
,
statusBar
,
...
...
@@ -80,7 +81,8 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
final
BoxConstraints
fullWidthConstraints
=
looseConstraints
.
tighten
(
width:
size
.
width
);
double
contentTop
=
padding
.
top
;
double
contentBottom
=
size
.
height
-
padding
.
bottom
;
double
bottom
=
size
.
height
-
padding
.
bottom
;
double
contentBottom
=
bottom
;
if
(
hasChild
(
_ScaffoldSlot
.
appBar
))
{
final
double
appBarHeight
=
layoutChild
(
_ScaffoldSlot
.
appBar
,
fullWidthConstraints
).
height
;
...
...
@@ -89,6 +91,12 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
positionChild
(
_ScaffoldSlot
.
appBar
,
Offset
.
zero
);
}
if
(
hasChild
(
_ScaffoldSlot
.
bottomNavigationBar
))
{
final
double
bottomNavigationBarHeight
=
layoutChild
(
_ScaffoldSlot
.
bottomNavigationBar
,
fullWidthConstraints
).
height
;
contentBottom
-=
bottomNavigationBarHeight
;
positionChild
(
_ScaffoldSlot
.
bottomNavigationBar
,
new
Offset
(
0.0
,
contentBottom
));
}
if
(
hasChild
(
_ScaffoldSlot
.
body
))
{
final
double
bodyHeight
=
contentBottom
-
contentTop
;
final
BoxConstraints
bodyConstraints
=
fullWidthConstraints
.
tighten
(
height:
bodyHeight
);
...
...
@@ -97,7 +105,10 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
}
// The BottomSheet and the SnackBar are anchored to the bottom of the parent,
// they're as wide as the parent and are given their intrinsic height.
// they're as wide as the parent and are given their intrinsic height. The
// only difference is that SnackBar appears on the top side of the
// BottomNavigationBar while the BottomSheet is stacked on top of it.
//
// If all three elements are present then either the center of the FAB straddles
// the top edge of the BottomSheet or the bottom of the FAB is
// _kFloatingActionButtonMargin above the SnackBar, whichever puts the FAB
...
...
@@ -110,7 +121,7 @@ class _ScaffoldLayout extends MultiChildLayoutDelegate {
if
(
hasChild
(
_ScaffoldSlot
.
bottomSheet
))
{
bottomSheetSize
=
layoutChild
(
_ScaffoldSlot
.
bottomSheet
,
fullWidthConstraints
);
positionChild
(
_ScaffoldSlot
.
bottomSheet
,
new
Offset
((
size
.
width
-
bottomSheetSize
.
width
)
/
2.0
,
contentB
ottom
-
bottomSheetSize
.
height
));
positionChild
(
_ScaffoldSlot
.
bottomSheet
,
new
Offset
((
size
.
width
-
bottomSheetSize
.
width
)
/
2.0
,
b
ottom
-
bottomSheetSize
.
height
));
}
if
(
hasChild
(
_ScaffoldSlot
.
snackBar
))
{
...
...
@@ -265,6 +276,7 @@ class _FloatingActionButtonTransitionState extends State<_FloatingActionButtonTr
/// * [AppBar]
/// * [FloatingActionButton]
/// * [Drawer]
/// * [BottomNavigationBar]
/// * [SnackBar]
/// * [BottomSheet]
/// * [ScaffoldState]
...
...
@@ -281,6 +293,7 @@ class Scaffold extends StatefulWidget {
this
.
body
,
this
.
floatingActionButton
,
this
.
drawer
,
this
.
bottomNavigationBar
,
this
.
scrollableKey
,
this
.
appBarBehavior
:
AppBarBehavior
.
anchor
,
this
.
resizeToAvoidBottomPadding
:
true
...
...
@@ -306,6 +319,12 @@ class Scaffold extends StatefulWidget {
/// Typically a [Drawer].
final
Widget
drawer
;
/// A bottom navigation bar to display at the bottom of the scaffold.
///
/// Snack bars slide from underneath the botton navigation while bottom sheets
/// are stacked on top.
final
Widget
bottomNavigationBar
;
/// The key of the primary [Scrollable] widget in the [body].
///
/// Used to control scroll-linked effects, such as the collapse of the
...
...
@@ -465,7 +484,7 @@ class ScaffoldState extends State<Scaffold> {
/// content of the app. A persistent bottom sheet remains visible even when
/// the user interacts with other parts of the app.
///
/// A closely related widget is
a modal bottom sheet, which is an alternative
/// A closely related widget is a modal bottom sheet, which is an alternative
/// to a menu or a dialog and prevents the user from interacting with the rest
/// of the app. Modal bottom sheets can be created and displayed with the
/// [showModalBottomSheet] function.
...
...
@@ -759,7 +778,18 @@ class ScaffoldState extends State<Scaffold> {
}
else
{
children
.
add
(
new
LayoutId
(
child:
_buildScrollableAppBar
(
context
,
padding
),
id:
_ScaffoldSlot
.
appBar
));
}
// Otherwise the AppBar will be part of a [app bar, body] Stack. See AppBarBehavior.scroll below.
// Otherwise the AppBar will be part of a [app bar, body] Stack. See
// AppBarBehavior.scroll below.
if
(
_snackBars
.
isNotEmpty
)
_addIfNonNull
(
children
,
_snackBars
.
first
.
_widget
,
_ScaffoldSlot
.
snackBar
);
if
(
config
.
bottomNavigationBar
!=
null
)
{
children
.
add
(
new
LayoutId
(
id:
_ScaffoldSlot
.
bottomNavigationBar
,
child:
config
.
bottomNavigationBar
));
}
if
(
_currentBottomSheet
!=
null
||
_dismissedBottomSheets
.
isNotEmpty
)
{
final
List
<
Widget
>
bottomSheets
=
<
Widget
>[];
...
...
@@ -774,9 +804,6 @@ class ScaffoldState extends State<Scaffold> {
_addIfNonNull
(
children
,
stack
,
_ScaffoldSlot
.
bottomSheet
);
}
if
(
_snackBars
.
isNotEmpty
)
_addIfNonNull
(
children
,
_snackBars
.
first
.
_widget
,
_ScaffoldSlot
.
snackBar
);
children
.
add
(
new
LayoutId
(
id:
_ScaffoldSlot
.
floatingActionButton
,
child:
new
_FloatingActionButtonTransition
(
...
...
packages/flutter/test/material/bottom_navigation_bar_test.dart
0 → 100644
View file @
3a6530d5
// Copyright 2016 The Chromium 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_test/flutter_test.dart'
;
void
main
(
)
{
testWidgets
(
'BottomNavigationBar callback test'
,
(
WidgetTester
tester
)
async
{
int
mutatedIndex
;
await
tester
.
pumpWidget
(
new
Scaffold
(
bottomNavigationBar:
new
BottomNavigationBar
(
labels:
<
DestinationLabel
>[
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
ac_unit
),
title:
new
Text
(
'AC'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_alarm
),
title:
new
Text
(
'Alarm'
)
)
],
onTap:
(
int
index
)
{
mutatedIndex
=
index
;
}
)
)
);
await
tester
.
tap
(
find
.
text
(
'Alarm'
));
expect
(
mutatedIndex
,
1
);
});
testWidgets
(
'BottomNavigationBar content test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Scaffold
(
bottomNavigationBar:
new
BottomNavigationBar
(
labels:
<
DestinationLabel
>[
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
ac_unit
),
title:
new
Text
(
'AC'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_alarm
),
title:
new
Text
(
'Alarm'
)
)
]
)
)
);
RenderBox
box
=
tester
.
renderObject
(
find
.
byType
(
BottomNavigationBar
));
expect
(
box
.
size
.
height
,
60.0
);
expect
(
find
.
text
(
'AC'
),
findsOneWidget
);
expect
(
find
.
text
(
'Alarm'
),
findsOneWidget
);
});
testWidgets
(
'BottomNavigationBar action size test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Scaffold
(
bottomNavigationBar:
new
BottomNavigationBar
(
type:
BottomNavigationBarType
.
shifting
,
labels:
<
DestinationLabel
>[
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
ac_unit
),
title:
new
Text
(
'AC'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_alarm
),
title:
new
Text
(
'Alarm'
)
)
]
)
)
);
Iterable
<
RenderBox
>
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
expect
(
actions
.
length
,
2
);
expect
(
actions
.
elementAt
(
0
).
size
.
width
,
158.4
);
expect
(
actions
.
elementAt
(
1
).
size
.
width
,
105.6
);
await
tester
.
pumpWidget
(
new
Scaffold
(
bottomNavigationBar:
new
BottomNavigationBar
(
currentIndex:
1
,
type:
BottomNavigationBarType
.
shifting
,
labels:
<
DestinationLabel
>[
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
ac_unit
),
title:
new
Text
(
'AC'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_alarm
),
title:
new
Text
(
'Alarm'
)
)
]
)
)
);
await
tester
.
pump
(
const
Duration
(
milliseconds:
200
));
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
expect
(
actions
.
length
,
2
);
expect
(
actions
.
elementAt
(
0
).
size
.
width
,
105.6
);
expect
(
actions
.
elementAt
(
1
).
size
.
width
,
158.4
);
});
testWidgets
(
'BottomNavigationBar multiple taps test'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
Scaffold
(
bottomNavigationBar:
new
BottomNavigationBar
(
type:
BottomNavigationBarType
.
shifting
,
labels:
<
DestinationLabel
>[
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
ac_unit
),
title:
new
Text
(
'AC'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_alarm
),
title:
new
Text
(
'Alarm'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
access_time
),
title:
new
Text
(
'Time'
)
),
new
DestinationLabel
(
icon:
new
Icon
(
Icons
.
add
),
title:
new
Text
(
'Add'
)
)
]
)
)
);
// We want to make sure that the last label does not get displaced,
// irrespective of how many taps happen on the first N - 1 labels and how
// they grow.
Iterable
<
RenderBox
>
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
Point
originalOrigin
=
actions
.
elementAt
(
3
).
localToGlobal
(
Point
.
origin
);
await
tester
.
tap
(
find
.
text
(
'AC'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
expect
(
actions
.
elementAt
(
3
).
localToGlobal
(
Point
.
origin
),
equals
(
originalOrigin
));
await
tester
.
tap
(
find
.
text
(
'Alarm'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
expect
(
actions
.
elementAt
(
3
).
localToGlobal
(
Point
.
origin
),
equals
(
originalOrigin
));
await
tester
.
tap
(
find
.
text
(
'Time'
));
await
tester
.
pump
();
await
tester
.
pump
(
const
Duration
(
milliseconds:
100
));
actions
=
tester
.
renderObjectList
(
find
.
byType
(
InkResponse
));
expect
(
actions
.
elementAt
(
3
).
localToGlobal
(
Point
.
origin
),
equals
(
originalOrigin
));
});
}
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