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
c707b53f
Commit
c707b53f
authored
Jun 20, 2016
by
Hans Muller
Committed by
GitHub
Jun 20, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
AppBar bottom widget, not necessarily a TabBar (#4631)
parent
ef6a4faa
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
81 additions
and
62 deletions
+81
-62
colors_demo.dart
examples/flutter_gallery/lib/demo/colors_demo.dart
+1
-1
scrollable_tabs_demo.dart
examples/flutter_gallery/lib/demo/scrollable_tabs_demo.dart
+1
-1
tabs_demo.dart
examples/flutter_gallery/lib/demo/tabs_demo.dart
+1
-1
tabs_fab_demo.dart
examples/flutter_gallery/lib/demo/tabs_fab_demo.dart
+1
-1
two_level_list_demo.dart
examples/flutter_gallery/lib/demo/two_level_list_demo.dart
+10
-9
demo.dart
examples/flutter_gallery/lib/gallery/demo.dart
+1
-1
stock_home.dart
examples/stocks/lib/stock_home.dart
+1
-1
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+43
-32
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+17
-13
tabs.dart
packages/flutter/lib/src/material/tabs.dart
+5
-2
No files found.
examples/flutter_gallery/lib/demo/colors_demo.dart
View file @
c707b53f
...
...
@@ -119,7 +119,7 @@ class ColorsDemo extends StatelessWidget {
appBar:
new
AppBar
(
elevation:
0
,
title:
new
Text
(
'Colors'
),
tabBar
:
new
TabBar
<
ColorSwatch
>(
bottom
:
new
TabBar
<
ColorSwatch
>(
isScrollable:
true
,
labels:
new
Map
<
ColorSwatch
,
TabLabel
>.
fromIterable
(
colorSwatches
,
value:
(
ColorSwatch
swatch
)
{
return
new
TabLabel
(
text:
swatch
.
name
);
...
...
examples/flutter_gallery/lib/demo/scrollable_tabs_demo.dart
View file @
c707b53f
...
...
@@ -71,7 +71,7 @@ class ScrollableTabsDemoState extends State<ScrollableTabsDemo> {
]
)
],
tabBar
:
new
TabBar
<
IconData
>(
bottom
:
new
TabBar
<
IconData
>(
isScrollable:
true
,
labels:
new
Map
<
IconData
,
TabLabel
>.
fromIterable
(
icons
,
...
...
examples/flutter_gallery/lib/demo/tabs_demo.dart
View file @
c707b53f
...
...
@@ -50,7 +50,7 @@ class TabsDemoState extends State<TabsDemo> {
appBarBehavior:
AppBarBehavior
.
under
,
appBar:
new
AppBar
(
title:
new
Text
(
'Tabs and scrolling'
),
tabBar
:
new
TabBar
<
_Page
>(
bottom
:
new
TabBar
<
_Page
>(
labels:
new
Map
<
_Page
,
TabLabel
>.
fromIterable
(
_pages
,
value:
(
_Page
page
)
{
return
new
TabLabel
(
text:
page
.
label
);
})
...
...
examples/flutter_gallery/lib/demo/tabs_fab_demo.dart
View file @
c707b53f
...
...
@@ -100,7 +100,7 @@ class _TabsFabDemoState extends State<TabsFabDemo> {
key:
scaffoldKey
,
appBar:
new
AppBar
(
title:
new
Text
(
'FAB per tab'
),
tabBar
:
new
TabBar
<
_Page
>(
bottom
:
new
TabBar
<
_Page
>(
labels:
new
Map
<
_Page
,
TabLabel
>.
fromIterable
(
pages
,
value:
(
_Page
page
)
=>
page
.
tabLabel
)
)
),
...
...
examples/flutter_gallery/lib/demo/two_level_list_demo.dart
View file @
c707b53f
...
...
@@ -16,15 +16,16 @@ class TwoLevelListDemo extends StatelessWidget {
children:
<
Widget
>[
new
TwoLevelListItem
(
title:
new
Text
(
'Top'
)),
new
TwoLevelSublist
(
title:
new
Text
(
'Sublist'
),
children:
<
Widget
>[
new
TwoLevelListItem
(
title:
new
Text
(
'One'
)),
new
TwoLevelListItem
(
title:
new
Text
(
'Two'
)),
new
TwoLevelListItem
(
title:
new
Text
(
'Free'
)),
new
TwoLevelListItem
(
title:
new
Text
(
'Four'
))
]
),
new
TwoLevelListItem
(
title:
new
Text
(
'Bottom'
))
title:
new
Text
(
'Sublist'
),
children:
<
Widget
>[
new
TwoLevelListItem
(
title:
new
Text
(
'One'
)),
new
TwoLevelListItem
(
title:
new
Text
(
'Two'
)),
// https://en.wikipedia.org/wiki/Free_Four
new
TwoLevelListItem
(
title:
new
Text
(
'Free'
)),
new
TwoLevelListItem
(
title:
new
Text
(
'Four'
))
]
),
new
TwoLevelListItem
(
title:
new
Text
(
'Bottom'
))
]
)
);
...
...
examples/flutter_gallery/lib/gallery/demo.dart
View file @
c707b53f
...
...
@@ -73,7 +73,7 @@ class TabbedComponentDemoScaffold extends StatelessWidget {
child:
new
Scaffold
(
appBar:
new
AppBar
(
title:
new
Text
(
title
),
tabBar
:
new
TabBar
<
ComponentDemoTabData
>(
bottom
:
new
TabBar
<
ComponentDemoTabData
>(
isScrollable:
true
,
labels:
ComponentDemoTabData
.
buildTabLabels
(
demos
)
)
...
...
examples/stocks/lib/stock_home.dart
View file @
c707b53f
...
...
@@ -241,7 +241,7 @@ class StockHomeState extends State<StockHome> {
]
)
],
tabBar
:
new
TabBar
<
StockHomeTab
>(
bottom
:
new
TabBar
<
StockHomeTab
>(
labels:
<
StockHomeTab
,
TabLabel
>{
StockHomeTab
.
market
:
new
TabLabel
(
text:
StockStrings
.
of
(
context
).
market
()),
StockHomeTab
.
portfolio
:
new
TabLabel
(
text:
StockStrings
.
of
(
context
).
portfolio
())
...
...
packages/flutter/lib/src/material/app_bar.dart
View file @
c707b53f
...
...
@@ -14,6 +14,14 @@ import 'tabs.dart';
import
'theme.dart'
;
import
'typography.dart'
;
/// A widget that can appear at the bottom of an [AppBar]. The [Scaffold] uses
/// the bottom widget's [bottomHeight] to handle layout for
/// [AppBarBehavior.scroll] and [AppBarBehavior.under].
abstract
class
AppBarBottomWidget
extends
Widget
{
/// Defines the height of the app bar's optional bottom widget.
double
get
bottomHeight
;
}
// TODO(eseidel) Toolbar needs to change size based on orientation:
// http://www.google.com/design/spec/layout/structure.html#structure-app-bar
// Mobile Landscape: 48dp
...
...
@@ -30,10 +38,13 @@ import 'typography.dart';
/// App bars are most commonly used in the [Scaffold.appBar] property, which
/// places the app bar at the top of the app.
///
/// The AppBar displays the toolbar widgets, [leading], [title],
/// and [actions], above the [tabBar] (if any). If a [flexibleSpace] widget is
/// specified then it is stacked behind the toolbar and tabbar. The [Scaffold]
/// typically creates the appbar with an initial height equal to [expandedHeight].
/// The AppBar displays the toolbar widgets, [leading], [title], and
/// [actions], above the [bottom] (if any). If a [flexibleSpace] widget is
/// specified then it is stacked behind the toolbar and the bottom widget.
/// The [Scaffold] typically creates the appbar with an initial height equal to
/// [expandedHeight]. If the [Scaffold.appBarBehavior] is set then the
/// AppBar's [collapsedHeight] and [bottomHeight] define how small the app bar
/// will become when the application is scrolled.
///
/// See also:
///
...
...
@@ -53,18 +64,16 @@ class AppBar extends StatelessWidget {
this
.
title
,
this
.
actions
,
this
.
flexibleSpace
,
this
.
tabBar
,
this
.
bottom
,
this
.
elevation
:
4
,
this
.
backgroundColor
,
this
.
brightness
,
this
.
textTheme
,
this
.
padding
:
EdgeInsets
.
zero
,
double
expandedHeight
,
double
collapsedHeight
,
double
minimumHeight
double
collapsedHeight
})
:
_expandedHeight
=
expandedHeight
,
_collapsedHeight
=
collapsedHeight
,
_minimumHeight
=
minimumHeight
,
super
(
key:
key
);
/// A widget to display before the [title].
...
...
@@ -77,7 +86,7 @@ class AppBar extends StatelessWidget {
/// field with an [IconButton] that calls [Navigator.pop].
final
Widget
leading
;
/// The primary widget displayed in the app
bar.
/// The primary widget displayed in the appbar.
///
/// Typically a [Text] widget containing a description of the current contents
/// of the app.
...
...
@@ -97,8 +106,10 @@ class AppBar extends StatelessWidget {
/// Typically a [FlexibleSpaceBar]. See [FlexibleSpaceBar] for details.
final
Widget
flexibleSpace
;
/// A horizontal bar of tabs to display at the bottom of the app bar.
final
TabBar
<
dynamic
>
tabBar
;
/// This widget appears across the bottom of the appbar.
///
/// Typically a [TabBar].
final
AppBarBottomWidget
bottom
;
/// The z-coordinate at which to place this app bar.
///
...
...
@@ -129,7 +140,6 @@ class AppBar extends StatelessWidget {
final
double
_expandedHeight
;
final
double
_collapsedHeight
;
final
double
_minimumHeight
;
/// Creates a copy of this app bar but with the given fields replaced with the new values.
AppBar
copyWith
({
...
...
@@ -138,6 +148,7 @@ class AppBar extends StatelessWidget {
Widget
title
,
List
<
Widget
>
actions
,
Widget
flexibleSpace
,
AppBarBottomWidget
bottom
,
int
elevation
,
Color
backgroundColor
,
Brightness
brightness
,
...
...
@@ -152,7 +163,7 @@ class AppBar extends StatelessWidget {
title:
title
??
this
.
title
,
actions:
actions
??
this
.
actions
,
flexibleSpace:
flexibleSpace
??
this
.
flexibleSpace
,
tabBar:
tabBar
??
this
.
tabBar
,
bottom:
bottom
??
this
.
bottom
,
elevation:
elevation
??
this
.
elevation
,
backgroundColor:
backgroundColor
??
this
.
backgroundColor
,
brightness:
brightness
??
this
.
brightness
,
...
...
@@ -163,31 +174,31 @@ class AppBar extends StatelessWidget {
);
}
double
get
_tabBarHeight
=>
tabBar
==
null
?
null
:
tabBar
.
minimumHeight
;
double
get
_toolBarHeight
=>
kToolBarHeight
;
/// By default, the height of the toolbar and the tabbar (if any).
/// The [Scaffold] gives its appbar this height initially. If a
/// The height of the bottom widget. The [Scaffold] uses this value to control
/// the size of the app bar when its appBarBehavior is [AppBarBehavior.scroll]
/// or [AppBarBehavior.under].
double
get
bottomHeight
=>
bottom
?.
bottomHeight
??
0.0
;
/// By default, the total height of the toolbar and the bottom widget (if any).
/// The [Scaffold] gives its app bar this height initially. If a
/// [flexibleSpace] widget is specified this height should be big
/// enough to accommodate whatever that widget contains.
double
get
expandedHeight
=>
_expandedHeight
??
(
_toolBarHeight
+
(
_tabBarHeight
??
0.0
)
);
double
get
expandedHeight
=>
_expandedHeight
??
(
_toolBarHeight
+
bottomHeight
);
/// By default, the height of the toolbar and the
tabbar
(if any).
/// By default, the height of the toolbar and the
bottom widget
(if any).
/// If the height of the app bar is constrained to be less than this value
/// the toolbar and tabbar are scrolled upwards, out of view.
double
get
collapsedHeight
=>
_collapsedHeight
??
(
_toolBarHeight
+
(
_tabBarHeight
??
0.0
));
double
get
minimumHeight
=>
_minimumHeight
??
_tabBarHeight
??
_toolBarHeight
;
/// then the toolbar and bottom widget are scrolled upwards, out of view.
double
get
collapsedHeight
=>
_collapsedHeight
??
(
_toolBarHeight
+
bottomHeight
);
// Defines the opacity of the toolbar's text and icons.
double
_toolBarOpacity
(
double
appBarHeight
,
double
statusBarHeight
)
{
return
((
appBarHeight
-
(
_tabBarHeight
??
0.0
)
-
statusBarHeight
)
/
_toolBarHeight
).
clamp
(
0.0
,
1.0
);
return
((
appBarHeight
-
bottomHeight
-
statusBarHeight
)
/
_toolBarHeight
).
clamp
(
0.0
,
1.0
);
}
double
_tabBarOpacity
(
double
appBarHeight
,
double
statusBarHeight
)
{
final
double
tabBarHeight
=
_tabBarHeight
??
0.0
;
return
((
appBarHeight
-
statusBarHeight
)
/
tabBarHeight
).
clamp
(
0.0
,
1.0
);
double
_bottomOpacity
(
double
appBarHeight
,
double
statusBarHeight
)
{
return
((
appBarHeight
-
statusBarHeight
)
/
bottomHeight
).
clamp
(
0.0
,
1.0
);
}
Widget
_buildForSize
(
BuildContext
context
,
BoxConstraints
constraints
)
{
...
...
@@ -254,15 +265,15 @@ class AppBar extends StatelessWidget {
)
);
final
double
tabBarOpacity
=
_tabBar
Opacity
(
size
.
height
,
statusBarHeight
);
if
(
tabBar
!=
null
)
{
final
double
bottomOpacity
=
_bottom
Opacity
(
size
.
height
,
statusBarHeight
);
if
(
bottom
!=
null
)
{
appBar
=
new
Column
(
mainAxisAlignment:
MainAxisAlignment
.
spaceBetween
,
children:
<
Widget
>[
appBar
,
tabBarOpacity
==
1.0
?
tabBar
:
new
Opacity
(
child:
tabBar
,
opacity:
const
Interval
(
0.25
,
1.0
,
curve:
Curves
.
ease
).
transform
(
tabBar
Opacity
)
bottomOpacity
==
1.0
?
bottom
:
new
Opacity
(
child:
bottom
,
opacity:
const
Interval
(
0.25
,
1.0
,
curve:
Curves
.
ease
).
transform
(
bottom
Opacity
)
)
]
);
...
...
packages/flutter/lib/src/material/scaffold.dart
View file @
c707b53f
...
...
@@ -20,24 +20,27 @@ const double _kFloatingActionButtonMargin = 16.0; // TODO(hmuller): should be de
const
Duration
_kFloatingActionButtonSegue
=
const
Duration
(
milliseconds:
200
);
final
Tween
<
double
>
_kFloatingActionButtonTurnTween
=
new
Tween
<
double
>(
begin:
-
0.125
,
end:
0.0
);
/// The Scaffold's appbar is the toolbar,
tabbar, and the "flexible space" that's
///
stacked behind them. The Scaffold's appBarBehavior defines how the appbar
///
responds to scrolling the application
.
/// The Scaffold's appbar is the toolbar,
bottom, and the "flexible space"
///
that's stacked behind them. The Scaffold's appBarBehavior defines how
///
its layout responds to scrolling the application's body
.
enum
AppBarBehavior
{
/// The
tool
bar's layout does not respond to scrolling.
/// The
app
bar's layout does not respond to scrolling.
anchor
,
/// The
tool
bar's appearance and layout depend on the scrollOffset of the
/// The
app
bar's appearance and layout depend on the scrollOffset of the
/// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
/// at 0.0, scrolling downwards causes the toolbar's flexible space to shrink,
/// and then the entire toolbar fade outs and scrolls off the top of the screen.
/// Scrolling upwards always causes the toolbar to reappear.
/// and then the app bar fades out and scrolls off the top of the screen.
/// Scrolling upwards always causes the app bar's bottom widget to reappear
/// if the bottom widget isn't null, otherwise the app bar's toolbar reappears.
scroll
,
/// The
tool
bar's appearance and layout depend on the scrollOffset of the
/// The
app
bar's appearance and layout depend on the scrollOffset of the
/// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
/// at 0.0, Scrolling downwards causes the toolbar's flexible space to shrink.
/// Other than that, the toolbar remains anchored at the top.
/// If the bottom widget isn't null the app bar shrinks to the bottom widget's
/// [AppBarBottomWidget.bottomHeight], otherwise the app bar shrinks to its
/// [AppBar.collapsedHeight].
under
,
}
...
...
@@ -612,13 +615,14 @@ class ScaffoldState extends State<Scaffold> {
Widget
_buildScrollableAppBar
(
BuildContext
context
,
EdgeInsets
padding
)
{
final
double
expandedHeight
=
(
config
.
appBar
?.
expandedHeight
??
0.0
)
+
padding
.
top
;
final
double
collapsedHeight
=
(
config
.
appBar
?.
collapsedHeight
??
0.0
)
+
padding
.
top
;
final
double
minimumHeight
=
(
config
.
appBar
?.
minimumHeight
??
0.0
)
+
padding
.
top
;
final
double
bottomHeight
=
config
.
appBar
?.
bottomHeight
+
padding
.
top
;
final
double
underHeight
=
config
.
appBar
.
bottom
!=
null
?
bottomHeight
:
collapsedHeight
;
Widget
appBar
;
if
(
_scrollOffset
<=
expandedHeight
&&
_scrollOffset
>=
expandedHeight
-
minimum
Height
)
{
if
(
_scrollOffset
<=
expandedHeight
&&
_scrollOffset
>=
expandedHeight
-
under
Height
)
{
// scrolled to the top, flexible space collapsed, only the toolbar and tabbar are (partially) visible.
if
(
config
.
appBarBehavior
==
AppBarBehavior
.
under
)
{
appBar
=
_buildAnchoredAppBar
(
expandedHeight
,
minimum
Height
,
padding
);
appBar
=
_buildAnchoredAppBar
(
expandedHeight
,
under
Height
,
padding
);
}
else
{
final
double
height
=
math
.
max
(
_floatingAppBarHeight
,
expandedHeight
-
_scrollOffset
);
_appBarController
.
value
=
(
expandedHeight
-
height
)
/
expandedHeight
;
...
...
@@ -630,7 +634,7 @@ class ScaffoldState extends State<Scaffold> {
}
else
if
(
_scrollOffset
>
expandedHeight
)
{
// scrolled past the entire app bar, maybe show the "floating" toolbar.
if
(
config
.
appBarBehavior
==
AppBarBehavior
.
under
)
{
appBar
=
_buildAnchoredAppBar
(
expandedHeight
,
minimum
Height
,
padding
);
appBar
=
_buildAnchoredAppBar
(
expandedHeight
,
under
Height
,
padding
);
}
else
{
_floatingAppBarHeight
=
(
_floatingAppBarHeight
+
_scrollOffsetDelta
).
clamp
(
0.0
,
collapsedHeight
);
_appBarController
.
value
=
(
expandedHeight
-
_floatingAppBarHeight
)
/
expandedHeight
;
...
...
packages/flutter/lib/src/material/tabs.dart
View file @
c707b53f
...
...
@@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
import
'package:flutter/widgets.dart'
;
import
'package:meta/meta.dart'
;
import
'app_bar.dart'
;
import
'colors.dart'
;
import
'debug.dart'
;
import
'icon.dart'
;
...
...
@@ -643,7 +644,7 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
/// * [TabBarView]
/// * [AppBar.tabBar]
/// * <https://www.google.com/design/spec/components/tabs.html>
class
TabBar
<
T
>
extends
Scrollable
{
class
TabBar
<
T
>
extends
Scrollable
implements
AppBarBottomWidget
{
TabBar
({
Key
key
,
this
.
labels
,
...
...
@@ -671,7 +672,9 @@ class TabBar<T> extends Scrollable {
/// the color of the theme's body2 text color is used.
final
Color
labelColor
;
double
get
minimumHeight
{
/// The height of the tab labels and indicator.
@override
double
get
bottomHeight
{
for
(
TabLabel
label
in
labels
.
values
)
{
if
(
label
.
text
!=
null
&&
(
label
.
icon
!=
null
||
label
.
iconBuilder
!=
null
))
return
_kTextAndIconTabHeight
+
_kTabIndicatorHeight
;
...
...
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