Unverified Commit 82715394 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Conditionally apply clipping in StretchingOverscrollIndicator (#91389)

parent 8d9481b8
......@@ -2807,9 +2807,13 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
physics: widget.scrollPhysics,
dragStartBehavior: widget.dragStartBehavior,
restorationId: widget.restorationId,
scrollBehavior: widget.scrollBehavior ??
// Remove scrollbars if only single line
(_isMultiline ? null : ScrollConfiguration.of(context).copyWith(scrollbars: false)),
// If a ScrollBehavior is not provided, only apply scrollbars when
// multiline. The overscroll indicator should not be applied in
// either case, glowing or stretching.
scrollBehavior: widget.scrollBehavior ?? ScrollConfiguration.of(context).copyWith(
scrollbars: _isMultiline,
overscroll: false,
),
viewportBuilder: (BuildContext context, ViewportOffset offset) {
return CompositedTransformTarget(
link: _toolbarLayerLink,
......
......@@ -12,6 +12,7 @@ import 'package:flutter/scheduler.dart';
import 'basic.dart';
import 'framework.dart';
import 'media_query.dart';
import 'notification_listener.dart';
import 'scroll_notification.dart';
import 'ticker_provider.dart';
......@@ -737,6 +738,8 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
double mainAxisSize;
return NotificationListener<ScrollNotification>(
onNotification: _handleScrollNotification,
child: AnimatedBuilder(
......@@ -749,9 +752,11 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
switch (widget.axis) {
case Axis.horizontal:
x += stretch;
mainAxisSize = size.width;
break;
case Axis.vertical:
y += stretch;
mainAxisSize = size.height;
break;
}
......@@ -759,13 +764,21 @@ class _StretchingOverscrollIndicatorState extends State<StretchingOverscrollIndi
_lastOverscrollNotification?.overscroll ?? 0.0
);
return ClipRect(
child: Transform(
alignment: alignment,
transform: Matrix4.diagonal3Values(x, y, 1.0),
child: widget.child,
),
final double viewportDimension = _lastOverscrollNotification?.metrics.viewportDimension ?? mainAxisSize;
final Widget transform = Transform(
alignment: alignment,
transform: Matrix4.diagonal3Values(x, y, 1.0),
child: widget.child,
);
// Only clip if the viewport dimension is smaller than that of the
// screen size in the main axis. If the viewport takes up the whole
// screen, overflow from transforming the viewport is irrelevant.
if (stretch != 0.0 && viewportDimension != mainAxisSize) {
return ClipRect(child: transform);
}
return transform;
},
),
);
......
......@@ -11,9 +11,9 @@ import 'package:flutter_test/flutter_test.dart';
void main() {
Widget buildTest(
Key box1Key,
Key box2Key,
Key box3Key,
GlobalKey box1Key,
GlobalKey box2Key,
GlobalKey box3Key,
ScrollController controller, {
Axis axis = Axis.vertical,
bool reverse = false,
......@@ -30,34 +30,37 @@ void main() {
return Directionality(
textDirection: TextDirection.ltr,
child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(overscroll: false),
child: StretchingOverscrollIndicator(
axisDirection: axisDirection,
child: CustomScrollView(
reverse: reverse,
scrollDirection: axis,
controller: controller,
slivers: <Widget>[
SliverToBoxAdapter(child: Container(
color: const Color(0xD0FF0000),
key: box1Key,
height: 250.0,
width: 300.0,
)),
SliverToBoxAdapter(child: Container(
color: const Color(0xFFFFFF00),
key: box2Key,
height: 250.0,
width: 300.0,
)),
SliverToBoxAdapter(child: Container(
color: const Color(0xFF6200EA),
key: box3Key,
height: 250.0,
width: 300.0,
)),
],
child: MediaQuery(
data: const MediaQueryData(size: Size(800.0, 600.0)),
child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(overscroll: false),
child: StretchingOverscrollIndicator(
axisDirection: axisDirection,
child: CustomScrollView(
reverse: reverse,
scrollDirection: axis,
controller: controller,
slivers: <Widget>[
SliverToBoxAdapter(child: Container(
color: const Color(0xD0FF0000),
key: box1Key,
height: 250.0,
width: 300.0,
)),
SliverToBoxAdapter(child: Container(
color: const Color(0xFFFFFF00),
key: box2Key,
height: 250.0,
width: 300.0,
)),
SliverToBoxAdapter(child: Container(
color: const Color(0xFF6200EA),
key: box3Key,
height: 250.0,
width: 300.0,
)),
],
),
),
),
),
......@@ -65,9 +68,9 @@ void main() {
}
testWidgets('Stretch overscroll vertically', (WidgetTester tester) async {
final Key box1Key = UniqueKey();
final Key box2Key = UniqueKey();
final Key box3Key = UniqueKey();
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
await tester.pumpWidget(
buildTest(box1Key, box2Key, box3Key, controller),
......@@ -142,9 +145,9 @@ void main() {
});
testWidgets('Stretch overscroll works in reverse - vertical', (WidgetTester tester) async {
final Key box1Key = UniqueKey();
final Key box2Key = UniqueKey();
final Key box3Key = UniqueKey();
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
await tester.pumpWidget(
buildTest(box1Key, box2Key, box3Key, controller, reverse: true),
......@@ -175,9 +178,9 @@ void main() {
});
testWidgets('Stretch overscroll works in reverse - horizontal', (WidgetTester tester) async {
final Key box1Key = UniqueKey();
final Key box2Key = UniqueKey();
final Key box3Key = UniqueKey();
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
await tester.pumpWidget(
buildTest(
......@@ -203,11 +206,11 @@ void main() {
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(CustomScrollView)));
// Overscroll
await gesture.moveBy(const Offset(200.0, 0.0));
await gesture.moveBy(const Offset(-200.0, 0.0));
await tester.pumpAndSettle();
expect(box1.localToGlobal(Offset.zero).dx, greaterThan(500.0));
expect(box2.localToGlobal(Offset.zero).dx, greaterThan(200.0));
expect(box3.localToGlobal(Offset.zero).dx, greaterThan(-100.0));
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.reverse.png'),
......@@ -215,9 +218,9 @@ void main() {
});
testWidgets('Stretch overscroll horizontally', (WidgetTester tester) async {
final Key box1Key = UniqueKey();
final Key box2Key = UniqueKey();
final Key box3Key = UniqueKey();
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)
......@@ -292,9 +295,9 @@ void main() {
});
testWidgets('Disallow stretching overscroll', (WidgetTester tester) async {
final Key box1Key = UniqueKey();
final Key box2Key = UniqueKey();
final Key box3Key = UniqueKey();
final GlobalKey box1Key = GlobalKey();
final GlobalKey box2Key = GlobalKey();
final GlobalKey box3Key = GlobalKey();
final ScrollController controller = ScrollController();
double indicatorNotification =0;
await tester.pumpWidget(
......@@ -337,34 +340,37 @@ void main() {
// Regression test for https://github.com/flutter/flutter/issues/90197
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(overscroll: false),
child: Column(
children: <Widget>[
StretchingOverscrollIndicator(
axisDirection: AxisDirection.down,
child: SizedBox(
height: 300,
child: ListView.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Index $index'),
);
},
child: MediaQuery(
data: const MediaQueryData(size: Size(800.0, 600.0)),
child: ScrollConfiguration(
behavior: const ScrollBehavior().copyWith(overscroll: false),
child: Column(
children: <Widget>[
StretchingOverscrollIndicator(
axisDirection: AxisDirection.down,
child: SizedBox(
height: 300,
child: ListView.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index){
return Padding(
padding: const EdgeInsets.all(10.0),
child: Text('Index $index'),
);
},
),
),
),
),
Opacity(
opacity: 0.5,
child: Container(
color: const Color(0xD0FF0000),
height: 100,
),
)
],
)
Opacity(
opacity: 0.5,
child: Container(
color: const Color(0xD0FF0000),
height: 100,
),
)
],
)
),
)
));
......
......@@ -105,17 +105,20 @@ void main() {
testWidgets('ScrollBehavior stretch android overscroll indicator', (WidgetTester tester) async {
await tester.pumpWidget(Directionality(
textDirection: TextDirection.ltr,
child: ScrollConfiguration(
behavior: const ScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
child: ListView(
children: const <Widget>[
SizedBox(
height: 1000.0,
width: 1000.0,
child: Text('Test'),
)
]
)
child: MediaQuery(
data: const MediaQueryData(size: Size(800, 600)),
child: ScrollConfiguration(
behavior: const ScrollBehavior(androidOverscrollIndicator: AndroidOverscrollIndicator.stretch),
child: ListView(
children: const <Widget>[
SizedBox(
height: 1000.0,
width: 1000.0,
child: Text('Test'),
)
]
)
),
),
));
......
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