Commit 566cacbd authored by Hans Muller's avatar Hans Muller Committed by GitHub

Don't leave tabs hanging in the middle (#5153)

parent c674b4a8
...@@ -1217,8 +1217,10 @@ class _TabBarViewState<T> extends PageableListState<TabBarView<T>> implements Ta ...@@ -1217,8 +1217,10 @@ class _TabBarViewState<T> extends PageableListState<TabBarView<T>> implements Ta
if (scrollVelocity.abs() > _kMinFlingVelocity) { if (scrollVelocity.abs() > _kMinFlingVelocity) {
final int selectionDelta = scrollVelocity.sign.truncate(); final int selectionDelta = scrollVelocity.sign.truncate();
final int targetIndex = (_selection.index + selectionDelta).clamp(0, _tabCount - 1); final int targetIndex = (_selection.index + selectionDelta).clamp(0, _tabCount - 1);
_selection.value = _selection.values[targetIndex]; if (_selection.index != targetIndex) {
return new Future<Null>.value(); _selection.value = _selection.values[targetIndex];
return new Future<Null>.value();
}
} }
final int selectionIndex = _selection.index; final int selectionIndex = _selection.index;
......
...@@ -31,7 +31,6 @@ Widget buildFrame({ List<String> tabs, String value, bool isScrollable: false, K ...@@ -31,7 +31,6 @@ Widget buildFrame({ List<String> tabs, String value, bool isScrollable: false, K
child: new TabBarSelection<String>( child: new TabBarSelection<String>(
value: value, value: value,
values: tabs, values: tabs,
onChanged: null,
child: new TabBar<String>( child: new TabBar<String>(
key: tabBarKey, key: tabBarKey,
labels: new Map<String, TabLabel>.fromIterable(tabs, value: (String tab) => new TabLabel(text: tab)), labels: new Map<String, TabLabel>.fromIterable(tabs, value: (String tab) => new TabLabel(text: tab)),
...@@ -41,6 +40,31 @@ Widget buildFrame({ List<String> tabs, String value, bool isScrollable: false, K ...@@ -41,6 +40,31 @@ Widget buildFrame({ List<String> tabs, String value, bool isScrollable: false, K
); );
} }
Widget buildLeftRightApp({ List<String> tabs, String value }) {
return new MaterialApp(
theme: new ThemeData(platform: TargetPlatform.android),
home: new TabBarSelection<String>(
value: value,
values: tabs,
child: new Scaffold(
appBar: new AppBar(
title: new Text('tabs'),
bottom: new TabBar<String>(
labels: new Map<String, TabLabel>.fromIterable(tabs, value: (String tab) => new TabLabel(text: tab)),
)
),
body: new TabBarView<String>(
children: <Widget>[
new Center(child: new Text('LEFT CHILD')),
new Center(child: new Text('RIGHT CHILD'))
]
)
)
)
);
}
void main() { void main() {
testWidgets('TabBar tap selects tab', (WidgetTester tester) async { testWidgets('TabBar tap selects tab', (WidgetTester tester) async {
List<String> tabs = <String>['A', 'B', 'C']; List<String> tabs = <String>['A', 'B', 'C'];
...@@ -228,4 +252,61 @@ void main() { ...@@ -228,4 +252,61 @@ void main() {
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
expect(findStateMarkerState(tabs[1]).marker, equals('marked')); expect(findStateMarkerState(tabs[1]).marker, equals('marked'));
}); });
testWidgets('TabBar left/right fling', (WidgetTester tester) async {
List<String> tabs = <String>['LEFT', 'RIGHT'];
await tester.pumpWidget(buildLeftRightApp(tabs: tabs, value: 'LEFT'));
expect(find.text('LEFT'), findsOneWidget);
expect(find.text('RIGHT'), findsOneWidget);
expect(find.text('LEFT CHILD'), findsOneWidget);
expect(find.text('RIGHT CHILD'), findsNothing);
TabBarSelectionState<String> selection = TabBarSelection.of(tester.element(find.text('LEFT')));
expect(selection.value, equals('LEFT'));
// Fling to the left, switch from the 'LEFT' tab to the 'RIGHT'
Point flingStart = tester.getCenter(find.text('LEFT CHILD'));
await tester.flingFrom(flingStart, new Offset(-200.0, 0.0), 1000.0);
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
expect(selection.value, equals('RIGHT'));
expect(find.text('LEFT CHILD'), findsNothing);
expect(find.text('RIGHT CHILD'), findsOneWidget);
// Fling to the right, switch back to the 'LEFT' tab
flingStart = tester.getCenter(find.text('RIGHT CHILD'));
await tester.flingFrom(flingStart, new Offset(200.0, 0.0), 1000.0);
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
expect(selection.value, equals('LEFT'));
expect(find.text('LEFT CHILD'), findsOneWidget);
expect(find.text('RIGHT CHILD'), findsNothing);
});
// A regression test for https://github.com/flutter/flutter/issues/5095
testWidgets('TabBar left/right fling reverse', (WidgetTester tester) async {
List<String> tabs = <String>['LEFT', 'RIGHT'];
await tester.pumpWidget(buildLeftRightApp(tabs: tabs, value: 'LEFT'));
expect(find.text('LEFT'), findsOneWidget);
expect(find.text('RIGHT'), findsOneWidget);
expect(find.text('LEFT CHILD'), findsOneWidget);
expect(find.text('RIGHT CHILD'), findsNothing);
TabBarSelectionState<String> selection = TabBarSelection.of(tester.element(find.text('LEFT')));
expect(selection.value, equals('LEFT'));
// End the fling by reversing direction. This should cause not cause
// a change to the selected tab, everything should just settle back to
// to where it started.
Point flingStart = tester.getCenter(find.text('LEFT CHILD'));
await tester.flingFrom(flingStart, new Offset(-200.0, 0.0), -1000.0);
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // finish the scroll animation
expect(selection.value, equals('LEFT'));
expect(find.text('LEFT CHILD'), findsOneWidget);
expect(find.text('RIGHT CHILD'), findsNothing);
});
} }
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