adds properties to dismissible widget (#14162)
* adds crossAxisEndOffset and rollbackDuration properties to dismissible widget * re-added removed license comment * corrected license comments * Adds test for rollbackDuration and crossAxisEndOffset * added tests and comments * modified tests for dismissible widgets
This commit is contained in:
parent
c54fab0444
commit
47e52b827f
@ -12,7 +12,6 @@ import 'gesture_detector.dart';
|
|||||||
import 'ticker_provider.dart';
|
import 'ticker_provider.dart';
|
||||||
import 'transitions.dart';
|
import 'transitions.dart';
|
||||||
|
|
||||||
const Duration _kDismissDuration = const Duration(milliseconds: 200);
|
|
||||||
const Curve _kResizeTimeCurve = const Interval(0.4, 1.0, curve: Curves.ease);
|
const Curve _kResizeTimeCurve = const Interval(0.4, 1.0, curve: Curves.ease);
|
||||||
const double _kMinFlingVelocity = 700.0;
|
const double _kMinFlingVelocity = 700.0;
|
||||||
const double _kMinFlingVelocityDelta = 400.0;
|
const double _kMinFlingVelocityDelta = 400.0;
|
||||||
@ -83,6 +82,8 @@ class Dismissible extends StatefulWidget {
|
|||||||
this.direction: DismissDirection.horizontal,
|
this.direction: DismissDirection.horizontal,
|
||||||
this.resizeDuration: const Duration(milliseconds: 300),
|
this.resizeDuration: const Duration(milliseconds: 300),
|
||||||
this.dismissThresholds: const <DismissDirection, double>{},
|
this.dismissThresholds: const <DismissDirection, double>{},
|
||||||
|
this.movementDuration: const Duration(milliseconds: 200),
|
||||||
|
this.crossAxisEndOffset: 0.0,
|
||||||
}) : assert(key != null),
|
}) : assert(key != null),
|
||||||
assert(secondaryBackground != null ? background != null : true),
|
assert(secondaryBackground != null ? background != null : true),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@ -134,6 +135,15 @@ class Dismissible extends StatefulWidget {
|
|||||||
/// [direction] property.
|
/// [direction] property.
|
||||||
final Map<DismissDirection, double> dismissThresholds;
|
final Map<DismissDirection, double> dismissThresholds;
|
||||||
|
|
||||||
|
/// Defines the duration for card to dismiss or to come back to original position if not dismissed.
|
||||||
|
final Duration movementDuration;
|
||||||
|
|
||||||
|
/// Defines the end offset across the main axis after the card is dismissed.
|
||||||
|
///
|
||||||
|
/// If non-zero value is given then widget moves in cross direction depending on whether
|
||||||
|
/// it is positive or negative.
|
||||||
|
final double crossAxisEndOffset;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_DismissibleState createState() => new _DismissibleState();
|
_DismissibleState createState() => new _DismissibleState();
|
||||||
}
|
}
|
||||||
@ -183,7 +193,7 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_moveController = new AnimationController(duration: _kDismissDuration, vsync: this)
|
_moveController = new AnimationController(duration: widget.movementDuration, vsync: this)
|
||||||
..addStatusListener(_handleDismissStatusChanged);
|
..addStatusListener(_handleDismissStatusChanged);
|
||||||
_updateMoveAnimation();
|
_updateMoveAnimation();
|
||||||
}
|
}
|
||||||
@ -317,7 +327,9 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
|
|||||||
final double end = _dragExtent.sign;
|
final double end = _dragExtent.sign;
|
||||||
_moveAnimation = new Tween<Offset>(
|
_moveAnimation = new Tween<Offset>(
|
||||||
begin: Offset.zero,
|
begin: Offset.zero,
|
||||||
end: _directionIsXAxis ? new Offset(end, 0.0) : new Offset(0.0, end),
|
end: _directionIsXAxis
|
||||||
|
? new Offset(end, widget.crossAxisEndOffset)
|
||||||
|
: new Offset(widget.crossAxisEndOffset, end),
|
||||||
).animate(_moveController);
|
).animate(_moveController);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -513,3 +525,4 @@ class _DismissibleState extends State<Dismissible> with TickerProviderStateMixin
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ DismissDirection dismissDirection = DismissDirection.horizontal;
|
|||||||
DismissDirection reportedDismissDirection;
|
DismissDirection reportedDismissDirection;
|
||||||
List<int> dismissedItems = <int>[];
|
List<int> dismissedItems = <int>[];
|
||||||
Widget background;
|
Widget background;
|
||||||
|
const double crossAxisEndOffset = 0.5;
|
||||||
|
|
||||||
Widget buildTest({ double startToEndThreshold, TextDirection textDirection: TextDirection.ltr }) {
|
Widget buildTest({ double startToEndThreshold, TextDirection textDirection: TextDirection.ltr }) {
|
||||||
return new Directionality(
|
return new Directionality(
|
||||||
@ -37,6 +38,7 @@ Widget buildTest({ double startToEndThreshold, TextDirection textDirection: Text
|
|||||||
dismissThresholds: startToEndThreshold == null
|
dismissThresholds: startToEndThreshold == null
|
||||||
? <DismissDirection, double>{}
|
? <DismissDirection, double>{}
|
||||||
: <DismissDirection, double>{DismissDirection.startToEnd: startToEndThreshold},
|
: <DismissDirection, double>{DismissDirection.startToEnd: startToEndThreshold},
|
||||||
|
crossAxisEndOffset: crossAxisEndOffset,
|
||||||
child: new Container(
|
child: new Container(
|
||||||
width: itemExtent,
|
width: itemExtent,
|
||||||
height: itemExtent,
|
height: itemExtent,
|
||||||
@ -143,6 +145,53 @@ Future<Null> dismissItem(WidgetTester tester, int item, {
|
|||||||
await tester.pump(); // rebuild after the callback removes the entry
|
await tester.pump(); // rebuild after the callback removes the entry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Null> checkFlingItemBeforeMovementEnd(WidgetTester tester, int item, {
|
||||||
|
@required AxisDirection gestureDirection,
|
||||||
|
DismissMethod mechanism: rollbackElement
|
||||||
|
}) async {
|
||||||
|
assert(gestureDirection != null);
|
||||||
|
final Finder itemFinder = find.text(item.toString());
|
||||||
|
expect(itemFinder, findsOneWidget);
|
||||||
|
|
||||||
|
await mechanism(tester, itemFinder, gestureDirection: gestureDirection);
|
||||||
|
|
||||||
|
await tester.pump(); // start the slide
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Null> checkFlingItemAfterMovement(WidgetTester tester, int item, {
|
||||||
|
@required AxisDirection gestureDirection,
|
||||||
|
DismissMethod mechanism: rollbackElement
|
||||||
|
}) async {
|
||||||
|
assert(gestureDirection != null);
|
||||||
|
final Finder itemFinder = find.text(item.toString());
|
||||||
|
expect(itemFinder, findsOneWidget);
|
||||||
|
|
||||||
|
await mechanism(tester, itemFinder, gestureDirection: gestureDirection);
|
||||||
|
|
||||||
|
await tester.pump(); // start the slide
|
||||||
|
await tester.pump(const Duration(milliseconds: 300));
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Null> rollbackElement(WidgetTester tester, Finder finder, { @required AxisDirection gestureDirection, double initialOffsetFactor: 0.0 }) async {
|
||||||
|
Offset delta;
|
||||||
|
switch (gestureDirection) {
|
||||||
|
case AxisDirection.left:
|
||||||
|
delta = const Offset(-30.0, 0.0);
|
||||||
|
break;
|
||||||
|
case AxisDirection.right:
|
||||||
|
delta = const Offset(30.0, 0.0);
|
||||||
|
break;
|
||||||
|
case AxisDirection.up:
|
||||||
|
delta = const Offset(0.0, -30.0);
|
||||||
|
break;
|
||||||
|
case AxisDirection.down:
|
||||||
|
delta = const Offset(0.0, 30.0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
await tester.fling(finder, delta, 1000.0, initialOffset: delta * initialOffsetFactor);
|
||||||
|
}
|
||||||
|
|
||||||
class Test1215DismissibleWidget extends StatelessWidget {
|
class Test1215DismissibleWidget extends StatelessWidget {
|
||||||
const Test1215DismissibleWidget(this.text);
|
const Test1215DismissibleWidget(this.text);
|
||||||
|
|
||||||
@ -558,4 +607,54 @@ void main() {
|
|||||||
final RenderBox backgroundBox = tester.firstRenderObject(find.text('background'));
|
final RenderBox backgroundBox = tester.firstRenderObject(find.text('background'));
|
||||||
expect(backgroundBox.size.height, equals(100.0));
|
expect(backgroundBox.size.height, equals(100.0));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
testWidgets('Checking fling item before movementDuration completes', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(buildTest());
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemBeforeMovementEnd(tester, 0, gestureDirection: AxisDirection.left, mechanism: flingElement);
|
||||||
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
|
||||||
|
await checkFlingItemBeforeMovementEnd(tester, 1, gestureDirection: AxisDirection.right, mechanism: flingElement);
|
||||||
|
expect(find.text('1'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Checking fling item after movementDuration', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(buildTest());
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 1, gestureDirection: AxisDirection.left, mechanism: flingElement);
|
||||||
|
expect(find.text('1'), findsNothing);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 0, gestureDirection: AxisDirection.right, mechanism: flingElement);
|
||||||
|
expect(find.text('0'), findsNothing);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Horizontal fling less than threshold', (WidgetTester tester) async {
|
||||||
|
scrollDirection = Axis.horizontal;
|
||||||
|
await tester.pumpWidget(buildTest());
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 0, gestureDirection: AxisDirection.left, mechanism: rollbackElement);
|
||||||
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 1, gestureDirection: AxisDirection.right, mechanism: rollbackElement);
|
||||||
|
expect(find.text('1'), findsOneWidget);
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Vertical fling less than threshold', (WidgetTester tester) async {
|
||||||
|
scrollDirection = Axis.vertical;
|
||||||
|
await tester.pumpWidget(buildTest());
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 0, gestureDirection: AxisDirection.left, mechanism: rollbackElement);
|
||||||
|
expect(find.text('0'), findsOneWidget);
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
|
||||||
|
await checkFlingItemAfterMovement(tester, 1, gestureDirection: AxisDirection.right, mechanism: rollbackElement);
|
||||||
|
expect(find.text('1'), findsOneWidget);
|
||||||
|
expect(dismissedItems, isEmpty);
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user