Commit d682c13b authored by Hans Muller's avatar Hans Muller

First drag moves selected tab indicator

parent 9a4c2c68
...@@ -632,6 +632,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -632,6 +632,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
super.initState(); super.initState();
scrollBehavior.isScrollable = config.isScrollable; scrollBehavior.isScrollable = config.isScrollable;
_initSelection(TabBarSelection.of(context)); _initSelection(TabBarSelection.of(context));
_lastSelectedIndex = _selection.index;
} }
@override @override
...@@ -652,6 +653,30 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -652,6 +653,30 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
_selection = null; _selection = null;
} }
// Initialize _indicatorTween for interactive dragging between the tab on the left
// and the tab on the right. In this case _selection.animation.value is 0.5 when
// the indicator is below the selected tab, 0.0 when it's under the left tab, and 1.0
// when it's under the tab on the right.
void _initIndicatorTweenForDrag() {
assert(!_valueIsChanging);
_indicatorTween = new RectTween(
begin: _tabIndicatorRect(math.max(0, _selection.index - 1)),
end: _tabIndicatorRect(math.min(config.labels.length - 1, _selection.index + 1))
);
}
// Initialize _indicatorTween for animating the selected tab indicator from the
// previously selected tab to the newly selected one. In this case
// _selection.animation.value is 0.0 when the indicator is below the previously
// selected tab, and 1.0 when it's under the newly selected one.
void _initIndicatorTweenForAnimation() {
assert(_valueIsChanging);
_indicatorTween = new RectTween(
begin: _indicatorRect ?? _tabIndicatorRect(_selection.previousIndex),
end: _tabIndicatorRect(_selection.index)
);
}
@override @override
void handleStatusChange(AnimationStatus status) { void handleStatusChange(AnimationStatus status) {
if (config.labels.length == 0) if (config.labels.length == 0)
...@@ -659,10 +684,8 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -659,10 +684,8 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
if (_valueIsChanging && status == AnimationStatus.completed) { if (_valueIsChanging && status == AnimationStatus.completed) {
_valueIsChanging = false; _valueIsChanging = false;
_indicatorTween
..begin = _tabIndicatorRect(math.max(0, _selection.index - 1))
..end = _tabIndicatorRect(math.min(config.labels.length - 1, _selection.index + 1));
setState(() { setState(() {
_initIndicatorTweenForDrag();
_indicatorRect = _tabIndicatorRect(_selection.index); _indicatorRect = _tabIndicatorRect(_selection.index);
}); });
} }
...@@ -674,25 +697,26 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -674,25 +697,26 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
return; return;
if (_lastSelectedIndex != _selection.index) { if (_lastSelectedIndex != _selection.index) {
// Initialize our indicator animation when we change selected tabs. _valueIsChanging = true;
if (config.isScrollable) if (config.isScrollable)
scrollTo(_centeredTabScrollOffset(_selection.index), duration: _kTabBarScroll); scrollTo(_centeredTabScrollOffset(_selection.index), duration: _kTabBarScroll);
_indicatorTween _initIndicatorTweenForAnimation();
..begin = _indicatorRect ?? _tabIndicatorRect(_selection.previousIndex)
..end = _tabIndicatorRect(_selection.index);
_valueIsChanging = true;
_lastSelectedIndex = _selection.index; _lastSelectedIndex = _selection.index;
} else if (_indicatorTween == null) {
_initIndicatorTweenForDrag();
} }
Rect oldRect = _indicatorRect; Rect oldRect = _indicatorRect;
double t = _selection.animation.value; double t = _selection.animation.value;
if (_valueIsChanging) {
// When _valueIsChanging is true, we're animating based on a ticker and // When _valueIsChanging is false, we're animating based on drag gesture and
// want to curve the animation. When _valueIsChanging is false, we're // want linear selected tab indicator motion. When _valueIsChanging is true,
// animating based on a pointer event and want linear feedback. It's // a ticker is driving the selection change and we want to curve the animation.
// possible we should move this curve into the selection animation. // In this case the leading and trailing edges of the move at different rates.
// We animate the leading and trailing edges of the rect differently. // The easiest way to do this is to lerp 2 rects, and piece them together into 1.
// The easiest way to do this is to lerp 2 rects, and piece them together if (!_valueIsChanging) {
// into 1. _indicatorRect = _indicatorTween.lerp(t);
} else {
Rect leftRect, rightRect; Rect leftRect, rightRect;
if (_selection.index > _selection.previousIndex) { if (_selection.index > _selection.previousIndex) {
// Moving to the right - right edge is leading. // Moving to the right - right edge is leading.
...@@ -706,10 +730,6 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -706,10 +730,6 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
_indicatorRect = new Rect.fromLTRB( _indicatorRect = new Rect.fromLTRB(
leftRect.left, leftRect.top, rightRect.right, rightRect.bottom leftRect.left, leftRect.top, rightRect.right, rightRect.bottom
); );
} else {
// TODO(abarth): If we've never gone through handleStatusChange before, we
// might not have set up our _indicatorTween yet.
_indicatorRect = _indicatorTween.lerp(t);
} }
if (oldRect != _indicatorRect) if (oldRect != _indicatorRect)
setState(() { /* The indicator rect has changed. */ }); setState(() { /* The indicator rect has changed. */ });
...@@ -719,7 +739,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect ...@@ -719,7 +739,7 @@ class _TabBarState<T> extends ScrollableState<TabBar<T>> implements TabBarSelect
Size _tabBarSize; Size _tabBarSize;
List<double> _tabWidths; List<double> _tabWidths;
Rect _indicatorRect; Rect _indicatorRect;
RectTween _indicatorTween = new RectTween(); RectTween _indicatorTween;
Rect _tabRect(int tabIndex) { Rect _tabRect(int tabIndex) {
assert(_tabBarSize != null); assert(_tabBarSize != null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment