This commit is contained in:
Hans Muller 2015-08-25 09:40:30 -07:00
parent 1867b58c40
commit aaeaed9be8
2 changed files with 65 additions and 48 deletions

View File

@ -35,7 +35,6 @@ const double _kTextAndIconTabHeight = 72.0;
const double _kTabIndicatorHeight = 2.0; const double _kTabIndicatorHeight = 2.0;
const double _kMinTabWidth = 72.0; const double _kMinTabWidth = 72.0;
const double _kMaxTabWidth = 264.0; const double _kMaxTabWidth = 264.0;
const double _kRelativeMaxTabWidth = 56.0;
const EdgeDims _kTabLabelPadding = const EdgeDims.symmetric(horizontal: 12.0); const EdgeDims _kTabLabelPadding = const EdgeDims.symmetric(horizontal: 12.0);
const int _kTabIconSize = 24; const int _kTabIconSize = 24;
const double _kTabBarScrollDrag = 0.025; const double _kTabBarScrollDrag = 0.025;
@ -139,9 +138,8 @@ class RenderTabBar extends RenderBox with
return constraints.constrainWidth(width); return constraints.constrainWidth(width);
} }
double get _tabBarHeight { double get _tabHeight => textAndIcons ? _kTextAndIconTabHeight : _kTabHeight;
return (textAndIcons ? _kTextAndIconTabHeight : _kTabHeight) + _kTabIndicatorHeight; double get _tabBarHeight => _tabHeight + _kTabIndicatorHeight;
}
double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight(_tabBarHeight); double _getIntrinsicHeight(BoxConstraints constraints) => constraints.constrainHeight(_tabBarHeight);
@ -152,7 +150,7 @@ class RenderTabBar extends RenderBox with
void layoutFixedWidthTabs() { void layoutFixedWidthTabs() {
double tabWidth = size.width / childCount; double tabWidth = size.width / childCount;
BoxConstraints tabConstraints = BoxConstraints tabConstraints =
new BoxConstraints.tightFor(width: tabWidth, height: size.height); new BoxConstraints.tightFor(width: tabWidth, height: _tabHeight);
double x = 0.0; double x = 0.0;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
@ -164,12 +162,13 @@ class RenderTabBar extends RenderBox with
} }
} }
void layoutScrollableTabs() { double layoutScrollableTabs() {
BoxConstraints tabConstraints = new BoxConstraints( BoxConstraints tabConstraints = new BoxConstraints(
minWidth: _kMinTabWidth, minWidth: _kMinTabWidth,
maxWidth: math.min(size.width - _kRelativeMaxTabWidth, _kMaxTabWidth), maxWidth: _kMaxTabWidth,
minHeight: size.height, minHeight: _tabHeight,
maxHeight: size.height); maxHeight: _tabHeight
);
double x = 0.0; double x = 0.0;
RenderBox child = firstChild; RenderBox child = firstChild;
while (child != null) { while (child != null) {
@ -179,6 +178,7 @@ class RenderTabBar extends RenderBox with
x += child.size.width; x += child.size.width;
child = child.parentData.nextSibling; child = child.parentData.nextSibling;
} }
return x;
} }
Size layoutSize; Size layoutSize;
@ -209,17 +209,16 @@ class RenderTabBar extends RenderBox with
void performLayout() { void performLayout() {
assert(constraints is BoxConstraints); assert(constraints is BoxConstraints);
size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight));
assert(!size.isInfinite);
if (childCount == 0) if (childCount == 0)
return; return;
if (isScrollable) if (isScrollable) {
layoutScrollableTabs(); double tabBarWidth = layoutScrollableTabs();
else size = constraints.constrain(new Size(tabBarWidth, _tabBarHeight));
} else {
size = constraints.constrain(new Size(constraints.maxWidth, _tabBarHeight));
layoutFixedWidthTabs(); layoutFixedWidthTabs();
}
if (onLayoutChanged != null) if (onLayoutChanged != null)
reportLayoutChangedIfNeeded(); reportLayoutChangedIfNeeded();
@ -234,7 +233,7 @@ class RenderTabBar extends RenderBox with
return; return;
if (indicatorRect != null) { if (indicatorRect != null) {
canvas.drawRect(indicatorRect, new Paint()..color = indicatorColor); canvas.drawRect(indicatorRect.shift(offset), new Paint()..color = indicatorColor);
return; return;
} }
@ -404,6 +403,7 @@ class TabBar extends Scrollable {
bool isScrollable; bool isScrollable;
Size _tabBarSize; Size _tabBarSize;
Size _viewportSize = Size.zero;
List<double> _tabWidths; List<double> _tabWidths;
ValueAnimation<Rect> _indicatorAnimation; ValueAnimation<Rect> _indicatorAnimation;
@ -412,6 +412,7 @@ class TabBar extends Scrollable {
_indicatorAnimation = new ValueAnimation<Rect>() _indicatorAnimation = new ValueAnimation<Rect>()
..duration = _kTabBarScroll ..duration = _kTabBarScroll
..variable = new AnimatedRect(null, curve: ease); ..variable = new AnimatedRect(null, curve: ease);
scrollBehavior.isScrollable = isScrollable;
} }
void syncConstructorArguments(TabBar source) { void syncConstructorArguments(TabBar source) {
@ -447,7 +448,7 @@ class TabBar extends Scrollable {
if (tabIndex > 0) if (tabIndex > 0)
tabLeft = _tabWidths.take(tabIndex).reduce((sum, width) => sum + width); tabLeft = _tabWidths.take(tabIndex).reduce((sum, width) => sum + width);
double tabTop = 0.0; double tabTop = 0.0;
double tabBottom = _tabBarSize.height -_kTabIndicatorHeight; double tabBottom = _tabBarSize.height - _kTabIndicatorHeight;
double tabRight = tabLeft + _tabWidths[tabIndex]; double tabRight = tabLeft + _tabWidths[tabIndex];
return new Rect.fromLTRB(tabLeft, tabTop, tabRight, tabBottom); return new Rect.fromLTRB(tabLeft, tabTop, tabRight, tabBottom);
} }
@ -489,16 +490,26 @@ class TabBar extends Scrollable {
); );
} }
void _updateScrollBehavior() {
scrollBehavior.updateExtents(
containerExtent: scrollDirection == ScrollDirection.vertical ? _viewportSize.height : _viewportSize.width,
contentExtent: _tabWidths.reduce((sum, width) => sum + width)
);
}
void _layoutChanged(Size tabBarSize, List<double> tabWidths) { void _layoutChanged(Size tabBarSize, List<double> tabWidths) {
setState(() { setState(() {
_tabBarSize = tabBarSize; _tabBarSize = tabBarSize;
_tabWidths = tabWidths; _tabWidths = tabWidths;
scrollBehavior.updateExtents( _updateScrollBehavior();
containerExtent: _tabBarSize.width,
contentExtent: _tabWidths.reduce((sum, width) => sum + width));
}); });
} }
void _handleViewportSizeChanged(Size newSize) {
_viewportSize = newSize;
_updateScrollBehavior();
}
Widget buildContent() { Widget buildContent() {
assert(labels != null && labels.isNotEmpty); assert(labels != null && labels.isNotEmpty);
@ -531,35 +542,41 @@ class TabBar extends Scrollable {
textAndIcons = true; textAndIcons = true;
} }
Matrix4 transform = new Matrix4.identity(); Widget tabBar = new IconTheme(
transform.translate(-scrollOffset, 0.0); data: new IconThemeData(color: iconThemeColor),
child: new DefaultTextStyle(
return new Transform( style: textStyle,
transform: transform, child: new BuilderTransition(
child: new IconTheme( variables: [_indicatorRect],
data: new IconThemeData(color: iconThemeColor), direction: Direction.forward,
child: new DefaultTextStyle( performance: _indicatorAnimation,
style: textStyle, builder: () {
child: new BuilderTransition( return new TabBarWrapper(
variables: [_indicatorRect], children: tabs,
direction: Direction.forward, selectedIndex: selectedIndex,
performance: _indicatorAnimation, backgroundColor: backgroundColor,
builder: () { indicatorColor: indicatorColor,
return new TabBarWrapper( indicatorRect: _indicatorRect.value,
children: tabs, textAndIcons: textAndIcons,
selectedIndex: selectedIndex, isScrollable: isScrollable,
backgroundColor: backgroundColor, onLayoutChanged: _layoutChanged
indicatorColor: indicatorColor, );
indicatorRect: _indicatorRect.value, }
textAndIcons: textAndIcons,
isScrollable: isScrollable,
onLayoutChanged: _layoutChanged
);
}
)
) )
) )
); );
if (!isScrollable)
return tabBar;
return new SizeObserver(
callback: _handleViewportSizeChanged,
child: new Viewport(
scrollDirection: ScrollDirection.horizontal,
scrollOffset: new Offset(scrollOffset, 0.0),
child: tabBar
)
);
} }
} }