mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
AppBar bottom widget, not necessarily a TabBar (#4631)
This commit is contained in:
parent
ef6a4faa8d
commit
c707b53f01
@ -119,7 +119,7 @@ class ColorsDemo extends StatelessWidget {
|
|||||||
appBar: new AppBar(
|
appBar: new AppBar(
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
title: new Text('Colors'),
|
title: new Text('Colors'),
|
||||||
tabBar: new TabBar<ColorSwatch>(
|
bottom: new TabBar<ColorSwatch>(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
labels: new Map<ColorSwatch, TabLabel>.fromIterable(colorSwatches, value: (ColorSwatch swatch) {
|
labels: new Map<ColorSwatch, TabLabel>.fromIterable(colorSwatches, value: (ColorSwatch swatch) {
|
||||||
return new TabLabel(text: swatch.name);
|
return new TabLabel(text: swatch.name);
|
||||||
|
@ -71,7 +71,7 @@ class ScrollableTabsDemoState extends State<ScrollableTabsDemo> {
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
tabBar: new TabBar<IconData>(
|
bottom: new TabBar<IconData>(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
labels: new Map<IconData, TabLabel>.fromIterable(
|
labels: new Map<IconData, TabLabel>.fromIterable(
|
||||||
icons,
|
icons,
|
||||||
|
@ -50,7 +50,7 @@ class TabsDemoState extends State<TabsDemo> {
|
|||||||
appBarBehavior: AppBarBehavior.under,
|
appBarBehavior: AppBarBehavior.under,
|
||||||
appBar: new AppBar(
|
appBar: new AppBar(
|
||||||
title: new Text('Tabs and scrolling'),
|
title: new Text('Tabs and scrolling'),
|
||||||
tabBar: new TabBar<_Page>(
|
bottom: new TabBar<_Page>(
|
||||||
labels: new Map<_Page, TabLabel>.fromIterable(_pages, value: (_Page page) {
|
labels: new Map<_Page, TabLabel>.fromIterable(_pages, value: (_Page page) {
|
||||||
return new TabLabel(text: page.label);
|
return new TabLabel(text: page.label);
|
||||||
})
|
})
|
||||||
|
@ -100,7 +100,7 @@ class _TabsFabDemoState extends State<TabsFabDemo> {
|
|||||||
key: scaffoldKey,
|
key: scaffoldKey,
|
||||||
appBar: new AppBar(
|
appBar: new AppBar(
|
||||||
title: new Text('FAB per tab'),
|
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)
|
labels: new Map<_Page, TabLabel>.fromIterable(pages, value: (_Page page) => page.tabLabel)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -16,15 +16,16 @@ class TwoLevelListDemo extends StatelessWidget {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new TwoLevelListItem(title: new Text('Top')),
|
new TwoLevelListItem(title: new Text('Top')),
|
||||||
new TwoLevelSublist(
|
new TwoLevelSublist(
|
||||||
title: new Text('Sublist'),
|
title: new Text('Sublist'),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new TwoLevelListItem(title: new Text('One')),
|
new TwoLevelListItem(title: new Text('One')),
|
||||||
new TwoLevelListItem(title: new Text('Two')),
|
new TwoLevelListItem(title: new Text('Two')),
|
||||||
new TwoLevelListItem(title: new Text('Free')),
|
// https://en.wikipedia.org/wiki/Free_Four
|
||||||
new TwoLevelListItem(title: new Text('Four'))
|
new TwoLevelListItem(title: new Text('Free')),
|
||||||
]
|
new TwoLevelListItem(title: new Text('Four'))
|
||||||
),
|
]
|
||||||
new TwoLevelListItem(title: new Text('Bottom'))
|
),
|
||||||
|
new TwoLevelListItem(title: new Text('Bottom'))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -73,7 +73,7 @@ class TabbedComponentDemoScaffold extends StatelessWidget {
|
|||||||
child: new Scaffold(
|
child: new Scaffold(
|
||||||
appBar: new AppBar(
|
appBar: new AppBar(
|
||||||
title: new Text(title),
|
title: new Text(title),
|
||||||
tabBar: new TabBar<ComponentDemoTabData>(
|
bottom: new TabBar<ComponentDemoTabData>(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
labels: ComponentDemoTabData.buildTabLabels(demos)
|
labels: ComponentDemoTabData.buildTabLabels(demos)
|
||||||
)
|
)
|
||||||
|
@ -241,7 +241,7 @@ class StockHomeState extends State<StockHome> {
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
tabBar: new TabBar<StockHomeTab>(
|
bottom: new TabBar<StockHomeTab>(
|
||||||
labels: <StockHomeTab, TabLabel>{
|
labels: <StockHomeTab, TabLabel>{
|
||||||
StockHomeTab.market: new TabLabel(text: StockStrings.of(context).market()),
|
StockHomeTab.market: new TabLabel(text: StockStrings.of(context).market()),
|
||||||
StockHomeTab.portfolio: new TabLabel(text: StockStrings.of(context).portfolio())
|
StockHomeTab.portfolio: new TabLabel(text: StockStrings.of(context).portfolio())
|
||||||
|
@ -14,6 +14,14 @@ import 'tabs.dart';
|
|||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
import 'typography.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:
|
// TODO(eseidel) Toolbar needs to change size based on orientation:
|
||||||
// http://www.google.com/design/spec/layout/structure.html#structure-app-bar
|
// http://www.google.com/design/spec/layout/structure.html#structure-app-bar
|
||||||
// Mobile Landscape: 48dp
|
// Mobile Landscape: 48dp
|
||||||
@ -30,10 +38,13 @@ import 'typography.dart';
|
|||||||
/// App bars are most commonly used in the [Scaffold.appBar] property, which
|
/// App bars are most commonly used in the [Scaffold.appBar] property, which
|
||||||
/// places the app bar at the top of the app.
|
/// places the app bar at the top of the app.
|
||||||
///
|
///
|
||||||
/// The AppBar displays the toolbar widgets, [leading], [title],
|
/// The AppBar displays the toolbar widgets, [leading], [title], and
|
||||||
/// and [actions], above the [tabBar] (if any). If a [flexibleSpace] widget is
|
/// [actions], above the [bottom] (if any). If a [flexibleSpace] widget is
|
||||||
/// specified then it is stacked behind the toolbar and tabbar. The [Scaffold]
|
/// specified then it is stacked behind the toolbar and the bottom widget.
|
||||||
/// typically creates the appbar with an initial height equal to [expandedHeight].
|
/// 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:
|
/// See also:
|
||||||
///
|
///
|
||||||
@ -53,18 +64,16 @@ class AppBar extends StatelessWidget {
|
|||||||
this.title,
|
this.title,
|
||||||
this.actions,
|
this.actions,
|
||||||
this.flexibleSpace,
|
this.flexibleSpace,
|
||||||
this.tabBar,
|
this.bottom,
|
||||||
this.elevation: 4,
|
this.elevation: 4,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.brightness,
|
this.brightness,
|
||||||
this.textTheme,
|
this.textTheme,
|
||||||
this.padding: EdgeInsets.zero,
|
this.padding: EdgeInsets.zero,
|
||||||
double expandedHeight,
|
double expandedHeight,
|
||||||
double collapsedHeight,
|
double collapsedHeight
|
||||||
double minimumHeight
|
|
||||||
}) : _expandedHeight = expandedHeight,
|
}) : _expandedHeight = expandedHeight,
|
||||||
_collapsedHeight = collapsedHeight,
|
_collapsedHeight = collapsedHeight,
|
||||||
_minimumHeight = minimumHeight,
|
|
||||||
super(key: key);
|
super(key: key);
|
||||||
|
|
||||||
/// A widget to display before the [title].
|
/// A widget to display before the [title].
|
||||||
@ -77,7 +86,7 @@ class AppBar extends StatelessWidget {
|
|||||||
/// field with an [IconButton] that calls [Navigator.pop].
|
/// field with an [IconButton] that calls [Navigator.pop].
|
||||||
final Widget leading;
|
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
|
/// Typically a [Text] widget containing a description of the current contents
|
||||||
/// of the app.
|
/// of the app.
|
||||||
@ -97,8 +106,10 @@ class AppBar extends StatelessWidget {
|
|||||||
/// Typically a [FlexibleSpaceBar]. See [FlexibleSpaceBar] for details.
|
/// Typically a [FlexibleSpaceBar]. See [FlexibleSpaceBar] for details.
|
||||||
final Widget flexibleSpace;
|
final Widget flexibleSpace;
|
||||||
|
|
||||||
/// A horizontal bar of tabs to display at the bottom of the app bar.
|
/// This widget appears across the bottom of the appbar.
|
||||||
final TabBar<dynamic> tabBar;
|
///
|
||||||
|
/// Typically a [TabBar].
|
||||||
|
final AppBarBottomWidget bottom;
|
||||||
|
|
||||||
/// The z-coordinate at which to place this app bar.
|
/// The z-coordinate at which to place this app bar.
|
||||||
///
|
///
|
||||||
@ -129,7 +140,6 @@ class AppBar extends StatelessWidget {
|
|||||||
|
|
||||||
final double _expandedHeight;
|
final double _expandedHeight;
|
||||||
final double _collapsedHeight;
|
final double _collapsedHeight;
|
||||||
final double _minimumHeight;
|
|
||||||
|
|
||||||
/// Creates a copy of this app bar but with the given fields replaced with the new values.
|
/// Creates a copy of this app bar but with the given fields replaced with the new values.
|
||||||
AppBar copyWith({
|
AppBar copyWith({
|
||||||
@ -138,6 +148,7 @@ class AppBar extends StatelessWidget {
|
|||||||
Widget title,
|
Widget title,
|
||||||
List<Widget> actions,
|
List<Widget> actions,
|
||||||
Widget flexibleSpace,
|
Widget flexibleSpace,
|
||||||
|
AppBarBottomWidget bottom,
|
||||||
int elevation,
|
int elevation,
|
||||||
Color backgroundColor,
|
Color backgroundColor,
|
||||||
Brightness brightness,
|
Brightness brightness,
|
||||||
@ -152,7 +163,7 @@ class AppBar extends StatelessWidget {
|
|||||||
title: title ?? this.title,
|
title: title ?? this.title,
|
||||||
actions: actions ?? this.actions,
|
actions: actions ?? this.actions,
|
||||||
flexibleSpace: flexibleSpace ?? this.flexibleSpace,
|
flexibleSpace: flexibleSpace ?? this.flexibleSpace,
|
||||||
tabBar: tabBar ?? this.tabBar,
|
bottom: bottom ?? this.bottom,
|
||||||
elevation: elevation ?? this.elevation,
|
elevation: elevation ?? this.elevation,
|
||||||
backgroundColor: backgroundColor ?? this.backgroundColor,
|
backgroundColor: backgroundColor ?? this.backgroundColor,
|
||||||
brightness: brightness ?? this.brightness,
|
brightness: brightness ?? this.brightness,
|
||||||
@ -163,31 +174,31 @@ class AppBar extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double get _tabBarHeight => tabBar == null ? null : tabBar.minimumHeight;
|
|
||||||
|
|
||||||
double get _toolBarHeight => kToolBarHeight;
|
double get _toolBarHeight => kToolBarHeight;
|
||||||
|
|
||||||
/// By default, the height of the toolbar and the tabbar (if any).
|
/// The height of the bottom widget. The [Scaffold] uses this value to control
|
||||||
/// The [Scaffold] gives its appbar this height initially. If a
|
/// 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
|
/// [flexibleSpace] widget is specified this height should be big
|
||||||
/// enough to accommodate whatever that widget contains.
|
/// 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
|
/// 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.
|
/// then the toolbar and bottom widget are scrolled upwards, out of view.
|
||||||
double get collapsedHeight => _collapsedHeight ?? (_toolBarHeight + (_tabBarHeight ?? 0.0));
|
double get collapsedHeight => _collapsedHeight ?? (_toolBarHeight + bottomHeight);
|
||||||
|
|
||||||
double get minimumHeight => _minimumHeight ?? _tabBarHeight ?? _toolBarHeight;
|
|
||||||
|
|
||||||
// Defines the opacity of the toolbar's text and icons.
|
// Defines the opacity of the toolbar's text and icons.
|
||||||
double _toolBarOpacity(double appBarHeight, double statusBarHeight) {
|
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) {
|
double _bottomOpacity(double appBarHeight, double statusBarHeight) {
|
||||||
final double tabBarHeight = _tabBarHeight ?? 0.0;
|
return ((appBarHeight - statusBarHeight) / bottomHeight).clamp(0.0, 1.0);
|
||||||
return ((appBarHeight - statusBarHeight) / tabBarHeight).clamp(0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildForSize(BuildContext context, BoxConstraints constraints) {
|
Widget _buildForSize(BuildContext context, BoxConstraints constraints) {
|
||||||
@ -254,15 +265,15 @@ class AppBar extends StatelessWidget {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
final double tabBarOpacity = _tabBarOpacity(size.height, statusBarHeight);
|
final double bottomOpacity = _bottomOpacity(size.height, statusBarHeight);
|
||||||
if (tabBar != null) {
|
if (bottom != null) {
|
||||||
appBar = new Column(
|
appBar = new Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
appBar,
|
appBar,
|
||||||
tabBarOpacity == 1.0 ? tabBar : new Opacity(
|
bottomOpacity == 1.0 ? bottom : new Opacity(
|
||||||
child: tabBar,
|
child: bottom,
|
||||||
opacity: const Interval(0.25, 1.0, curve: Curves.ease).transform(tabBarOpacity)
|
opacity: const Interval(0.25, 1.0, curve: Curves.ease).transform(bottomOpacity)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -20,24 +20,27 @@ const double _kFloatingActionButtonMargin = 16.0; // TODO(hmuller): should be de
|
|||||||
const Duration _kFloatingActionButtonSegue = const Duration(milliseconds: 200);
|
const Duration _kFloatingActionButtonSegue = const Duration(milliseconds: 200);
|
||||||
final Tween<double> _kFloatingActionButtonTurnTween = new Tween<double>(begin: -0.125, end: 0.0);
|
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
|
/// The Scaffold's appbar is the toolbar, bottom, and the "flexible space"
|
||||||
/// stacked behind them. The Scaffold's appBarBehavior defines how the appbar
|
/// that's stacked behind them. The Scaffold's appBarBehavior defines how
|
||||||
/// responds to scrolling the application.
|
/// its layout responds to scrolling the application's body.
|
||||||
enum AppBarBehavior {
|
enum AppBarBehavior {
|
||||||
/// The tool bar's layout does not respond to scrolling.
|
/// The app bar's layout does not respond to scrolling.
|
||||||
anchor,
|
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
|
/// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
|
||||||
/// at 0.0, scrolling downwards causes the toolbar's flexible space to shrink,
|
/// 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.
|
/// and then the app bar fades out and scrolls off the top of the screen.
|
||||||
/// Scrolling upwards always causes the toolbar to reappear.
|
/// 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,
|
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
|
/// Scrollable identified by the Scaffold's scrollableKey. With the scrollOffset
|
||||||
/// at 0.0, Scrolling downwards causes the toolbar's flexible space to shrink.
|
/// 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,
|
under,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -612,13 +615,14 @@ class ScaffoldState extends State<Scaffold> {
|
|||||||
Widget _buildScrollableAppBar(BuildContext context, EdgeInsets padding) {
|
Widget _buildScrollableAppBar(BuildContext context, EdgeInsets padding) {
|
||||||
final double expandedHeight = (config.appBar?.expandedHeight ?? 0.0) + padding.top;
|
final double expandedHeight = (config.appBar?.expandedHeight ?? 0.0) + padding.top;
|
||||||
final double collapsedHeight = (config.appBar?.collapsedHeight ?? 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;
|
Widget appBar;
|
||||||
|
|
||||||
if (_scrollOffset <= expandedHeight && _scrollOffset >= expandedHeight - minimumHeight) {
|
if (_scrollOffset <= expandedHeight && _scrollOffset >= expandedHeight - underHeight) {
|
||||||
// scrolled to the top, flexible space collapsed, only the toolbar and tabbar are (partially) visible.
|
// scrolled to the top, flexible space collapsed, only the toolbar and tabbar are (partially) visible.
|
||||||
if (config.appBarBehavior == AppBarBehavior.under) {
|
if (config.appBarBehavior == AppBarBehavior.under) {
|
||||||
appBar = _buildAnchoredAppBar(expandedHeight, minimumHeight, padding);
|
appBar = _buildAnchoredAppBar(expandedHeight, underHeight, padding);
|
||||||
} else {
|
} else {
|
||||||
final double height = math.max(_floatingAppBarHeight, expandedHeight - _scrollOffset);
|
final double height = math.max(_floatingAppBarHeight, expandedHeight - _scrollOffset);
|
||||||
_appBarController.value = (expandedHeight - height) / expandedHeight;
|
_appBarController.value = (expandedHeight - height) / expandedHeight;
|
||||||
@ -630,7 +634,7 @@ class ScaffoldState extends State<Scaffold> {
|
|||||||
} else if (_scrollOffset > expandedHeight) {
|
} else if (_scrollOffset > expandedHeight) {
|
||||||
// scrolled past the entire app bar, maybe show the "floating" toolbar.
|
// scrolled past the entire app bar, maybe show the "floating" toolbar.
|
||||||
if (config.appBarBehavior == AppBarBehavior.under) {
|
if (config.appBarBehavior == AppBarBehavior.under) {
|
||||||
appBar = _buildAnchoredAppBar(expandedHeight, minimumHeight, padding);
|
appBar = _buildAnchoredAppBar(expandedHeight, underHeight, padding);
|
||||||
} else {
|
} else {
|
||||||
_floatingAppBarHeight = (_floatingAppBarHeight + _scrollOffsetDelta).clamp(0.0, collapsedHeight);
|
_floatingAppBarHeight = (_floatingAppBarHeight + _scrollOffsetDelta).clamp(0.0, collapsedHeight);
|
||||||
_appBarController.value = (expandedHeight - _floatingAppBarHeight) / expandedHeight;
|
_appBarController.value = (expandedHeight - _floatingAppBarHeight) / expandedHeight;
|
||||||
|
@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
|
|||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
|
|
||||||
|
import 'app_bar.dart';
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
import 'debug.dart';
|
import 'debug.dart';
|
||||||
import 'icon.dart';
|
import 'icon.dart';
|
||||||
@ -643,7 +644,7 @@ class TabBarSelectionState<T> extends State<TabBarSelection<T>> {
|
|||||||
/// * [TabBarView]
|
/// * [TabBarView]
|
||||||
/// * [AppBar.tabBar]
|
/// * [AppBar.tabBar]
|
||||||
/// * <https://www.google.com/design/spec/components/tabs.html>
|
/// * <https://www.google.com/design/spec/components/tabs.html>
|
||||||
class TabBar<T> extends Scrollable {
|
class TabBar<T> extends Scrollable implements AppBarBottomWidget {
|
||||||
TabBar({
|
TabBar({
|
||||||
Key key,
|
Key key,
|
||||||
this.labels,
|
this.labels,
|
||||||
@ -671,7 +672,9 @@ class TabBar<T> extends Scrollable {
|
|||||||
/// the color of the theme's body2 text color is used.
|
/// the color of the theme's body2 text color is used.
|
||||||
final Color labelColor;
|
final Color labelColor;
|
||||||
|
|
||||||
double get minimumHeight {
|
/// The height of the tab labels and indicator.
|
||||||
|
@override
|
||||||
|
double get bottomHeight {
|
||||||
for (TabLabel label in labels.values) {
|
for (TabLabel label in labels.values) {
|
||||||
if (label.text != null && (label.icon != null || label.iconBuilder != null))
|
if (label.text != null && (label.icon != null || label.iconBuilder != null))
|
||||||
return _kTextAndIconTabHeight + _kTabIndicatorHeight;
|
return _kTextAndIconTabHeight + _kTabIndicatorHeight;
|
||||||
|
Loading…
Reference in New Issue
Block a user