Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix stretch effect with rtl support #113214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions packages/flutter/lib/src/widgets/overscroll_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,7 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
return false;
}

AlignmentDirectional _getAlignmentForAxisDirection(double overscroll) {
AlignmentGeometry _getAlignmentForAxisDirection(double overscroll) {
// Accounts for reversed scrollables by checking the AxisDirection
switch (widget.axisDirection) {
case AxisDirection.up:
Expand All @@ -753,16 +753,16 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
: AlignmentDirectional.bottomCenter;
case AxisDirection.right:
return overscroll > 0
? AlignmentDirectional.centerEnd
: AlignmentDirectional.centerStart;
? Alignment.centerRight
: Alignment.centerLeft;
case AxisDirection.down:
return overscroll > 0
? AlignmentDirectional.bottomCenter
: AlignmentDirectional.topCenter;
case AxisDirection.left:
return overscroll > 0
? AlignmentDirectional.centerStart
: AlignmentDirectional.centerEnd;
? Alignment.centerLeft
: Alignment.centerRight;
}
}

Expand Down Expand Up @@ -796,7 +796,7 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
break;
}

final AlignmentDirectional alignment = _getAlignmentForAxisDirection(
final AlignmentGeometry alignment = _getAlignmentForAxisDirection(
_lastOverscrollNotification?.overscroll ?? 0.0
);

Expand Down
135 changes: 133 additions & 2 deletions packages/flutter/test/widgets/overscroll_stretch_indicator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,24 @@ void main() {
ScrollController controller, {
Axis axis = Axis.vertical,
bool reverse = false,
TextDirection textDirection = TextDirection.ltr,
}) {
final AxisDirection axisDirection;
switch (axis) {
case Axis.horizontal:
axisDirection = reverse ? AxisDirection.left : AxisDirection.right;
if (textDirection == TextDirection.rtl) {
axisDirection = reverse ? AxisDirection.right : AxisDirection.left;
} else {
axisDirection = reverse ? AxisDirection.left : AxisDirection.right;
}
break;
case Axis.vertical:
axisDirection = reverse ? AxisDirection.up : AxisDirection.down;
break;
}

return Directionality(
textDirection: TextDirection.ltr,
textDirection: textDirection,
child: MediaQuery(
data: const MediaQueryData(size: Size(800.0, 600.0)),
child: ScrollConfiguration(
Expand Down Expand Up @@ -218,6 +223,92 @@ void main() {
);
});

testWidgets('Stretch overscroll works in reverse - horizontal - RTL', (WidgetTester tester) async {
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
await tester.pumpWidget(
buildTest(
box1Key,
box2Key,
box3Key,
controller,
axis: Axis.horizontal,
reverse: true,
textDirection: TextDirection.rtl,
)
);

expect(find.byType(StretchingOverscrollIndicator), findsOneWidget);
expect(find.byType(GlowingOverscrollIndicator), findsNothing);
final RenderBox box1 = tester.renderObject(find.byKey(box1Key));
final RenderBox box2 = tester.renderObject(find.byKey(box2Key));
final RenderBox box3 = tester.renderObject(find.byKey(box3Key));

expect(controller.offset, 0.0);
expect(box1.localToGlobal(Offset.zero), Offset.zero);
expect(box2.localToGlobal(Offset.zero), const Offset(300.0, 0.0));
expect(box3.localToGlobal(Offset.zero), const Offset(600.0, 0.0));
await expectLater(
find.byType(CustomScrollView),
matchesGoldenFile('overscroll_stretch.horizontal.reverse.rtl.start.png'),
);

TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CustomScrollView)));
// Overscroll the start
await gesture.moveBy(const Offset(200.0, 0.0));
await tester.pumpAndSettle();

expect(box1.localToGlobal(Offset.zero), Offset.zero);
expect(box2.localToGlobal(Offset.zero).dx, greaterThan(305.0));
expect(box3.localToGlobal(Offset.zero).dx, greaterThan(610.0));
await expectLater(
find.byType(CustomScrollView),
matchesGoldenFile('overscroll_stretch.horizontal.reverse.rtl.start.stretched.png'),
);

await gesture.up();
await tester.pumpAndSettle();

// Stretch released back to the start
expect(box1.localToGlobal(Offset.zero), Offset.zero);
expect(box2.localToGlobal(Offset.zero), const Offset(300.0, 0.0));
expect(box3.localToGlobal(Offset.zero), const Offset(600.0, 0.0));

// Jump to end of the list
controller.jumpTo(controller.position.maxScrollExtent);
await tester.pumpAndSettle();
expect(controller.offset, 100.0);
expect(box1.localToGlobal(Offset.zero).dx, -100.0);
expect(box2.localToGlobal(Offset.zero).dx, 200.0);
expect(box3.localToGlobal(Offset.zero).dx, 500.0);
await expectLater(
find.byType(CustomScrollView),
matchesGoldenFile('overscroll_stretch.horizontal.reverse.rtl.end.png'),
);

gesture = await tester.startGesture(tester.getCenter(find.byType(CustomScrollView)));
// Overscroll the end
await gesture.moveBy(const Offset(-200.0, 0.0));
await tester.pumpAndSettle();
expect(box1.localToGlobal(Offset.zero).dx, lessThan(-116.0));
expect(box2.localToGlobal(Offset.zero).dx, lessThan(190.0));
expect(box3.localToGlobal(Offset.zero).dx, lessThan(500.0));
await expectLater(
find.byType(CustomScrollView),
matchesGoldenFile('overscroll_stretch.horizontal.reverse.rtl.end.stretched.png'),
);

await gesture.up();
await tester.pumpAndSettle();

// Stretch released back
expect(box1.localToGlobal(Offset.zero).dx, -100.0);
expect(box2.localToGlobal(Offset.zero).dx, 200.0);
expect(box3.localToGlobal(Offset.zero).dx, 500.0);
});

testWidgets('Stretch overscroll horizontally', (WidgetTester tester) async {
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
Expand Down Expand Up @@ -295,6 +386,46 @@ void main() {
expect(box3.localToGlobal(Offset.zero).dx, 500.0);
});

testWidgets('Stretch overscroll horizontally RTl', (WidgetTester tester) async {
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
await tester.pumpWidget(
buildTest(
box1Key,
box2Key,
box3Key,
controller,
axis: Axis.horizontal,
textDirection: TextDirection.rtl,
)
);

expect(find.byType(StretchingOverscrollIndicator), findsOneWidget);
expect(find.byType(GlowingOverscrollIndicator), findsNothing);
final RenderBox box1 = tester.renderObject(find.byKey(box1Key));
final RenderBox box2 = tester.renderObject(find.byKey(box2Key));
final RenderBox box3 = tester.renderObject(find.byKey(box3Key));

expect(controller.offset, 0.0);
expect(box1.localToGlobal(Offset.zero), const Offset(500.0, 0.0));
expect(box2.localToGlobal(Offset.zero), const Offset(200.0, 0.0));
expect(box3.localToGlobal(Offset.zero), const Offset(-100.0, 0.0));

final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CustomScrollView)));
// Overscroll
await gesture.moveBy(const Offset(-200.0, 0.0));
await tester.pumpAndSettle();
expect(box1.localToGlobal(Offset.zero).dx, lessThan(500.0));
expect(box2.localToGlobal(Offset.zero).dx, lessThan(200.0));
expect(box3.localToGlobal(Offset.zero).dx, lessThan(-100.0));
await expectLater(
find.byType(CustomScrollView),
matchesGoldenFile('overscroll_stretch.horizontal.rtl.png'),
);
});

testWidgets('Disallow stretching overscroll', (WidgetTester tester) async {
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
Expand Down