Skip to content

Commit 62cc326

Browse files
authored
Constrain app bar header paint origin on iOS overscroll (flutter#8517)
Prevent the app bar header from being overscrolled on iOS by setting paintOrigin to the overlap.
1 parent 1f7b8ae commit 62cc326

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

packages/flutter/lib/src/rendering/sliver_persistent_header.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
209209
final double paintExtent = maxExtent - constraints.scrollOffset;
210210
geometry = new SliverGeometry(
211211
scrollExtent: maxExtent,
212+
paintOrigin: math.min(constraints.overlap, 0.0),
212213
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
213214
maxPaintExtent: maxExtent,
214215
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
@@ -271,6 +272,7 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
271272
final double layoutExtent = maxExtent - constraints.scrollOffset;
272273
geometry = new SliverGeometry(
273274
scrollExtent: maxExtent,
275+
paintOrigin: math.min(constraints.overlap, 0.0),
274276
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
275277
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent),
276278
maxPaintExtent: maxExtent,

packages/flutter/test/widgets/slivers_appbar_floating_test.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,35 @@ void main() {
182182
verifyActualBoxPosition(tester, find.byType(Container), 0, new Rect.fromLTWH(0.0, -delegate.maxExtent * 0.4, 800.0, delegate.maxExtent * 0.5));
183183
verifyPaintPosition(key3, const Offset(0.0, 0.0), true);
184184
});
185+
186+
testWidgets('Sliver appbars - floating - overscroll gap is below header', (WidgetTester tester) async {
187+
await tester.pumpWidget(
188+
new CustomScrollView(
189+
physics: const BouncingScrollPhysics(),
190+
slivers: <Widget>[
191+
new SliverPersistentHeader(delegate: new TestDelegate(), floating: true),
192+
new SliverList(
193+
delegate: new SliverChildListDelegate(<Widget>[
194+
new SizedBox(
195+
height: 300.0,
196+
child: new Text('X'),
197+
),
198+
]),
199+
),
200+
],
201+
),
202+
);
203+
204+
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
205+
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 200.0));
206+
207+
ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
208+
position.jumpTo(-50.0);
209+
await tester.pump();
210+
211+
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
212+
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 250.0));
213+
});
185214
}
186215

187216
class TestDelegate extends SliverPersistentHeaderDelegate {

packages/flutter/test/widgets/slivers_appbar_scrolling_test.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,35 @@ void main() {
6767
Rect rect = new Rect.fromPoints(box.localToGlobal(Point.origin), box.localToGlobal(box.size.bottomRight(Point.origin)));
6868
expect(rect, equals(new Rect.fromLTWH(0.0, -195.0, 800.0, 200.0)));
6969
});
70+
71+
testWidgets('Sliver appbars - scrolling - overscroll gap is below header', (WidgetTester tester) async {
72+
await tester.pumpWidget(
73+
new CustomScrollView(
74+
physics: const BouncingScrollPhysics(),
75+
slivers: <Widget>[
76+
new SliverPersistentHeader(delegate: new TestDelegate()),
77+
new SliverList(
78+
delegate: new SliverChildListDelegate(<Widget>[
79+
new SizedBox(
80+
height: 300.0,
81+
child: new Text('X'),
82+
),
83+
]),
84+
),
85+
],
86+
),
87+
);
88+
89+
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
90+
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 200.0));
91+
92+
ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
93+
position.jumpTo(-50.0);
94+
await tester.pump();
95+
96+
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
97+
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 250.0));
98+
});
7099
}
71100

72101
class TestDelegate extends SliverPersistentHeaderDelegate {

0 commit comments

Comments
 (0)