Constrain app bar header paint origin on iOS overscroll (#8517)

Prevent the app bar header from being overscrolled on iOS by setting
paintOrigin to the overlap.
This commit is contained in:
Chris Bracken 2017-03-02 14:25:04 -08:00 committed by GitHub
parent 1f7b8ae11f
commit 62cc326a67
3 changed files with 60 additions and 0 deletions

View file

@ -209,6 +209,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
final double paintExtent = maxExtent - constraints.scrollOffset;
geometry = new SliverGeometry(
scrollExtent: maxExtent,
paintOrigin: math.min(constraints.overlap, 0.0),
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
maxPaintExtent: maxExtent,
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
@ -271,6 +272,7 @@ abstract class RenderSliverFloatingPersistentHeader extends RenderSliverPersiste
final double layoutExtent = maxExtent - constraints.scrollOffset;
geometry = new SliverGeometry(
scrollExtent: maxExtent,
paintOrigin: math.min(constraints.overlap, 0.0),
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent),
maxPaintExtent: maxExtent,

View file

@ -182,6 +182,35 @@ void main() {
verifyActualBoxPosition(tester, find.byType(Container), 0, new Rect.fromLTWH(0.0, -delegate.maxExtent * 0.4, 800.0, delegate.maxExtent * 0.5));
verifyPaintPosition(key3, const Offset(0.0, 0.0), true);
});
testWidgets('Sliver appbars - floating - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget(
new CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: <Widget>[
new SliverPersistentHeader(delegate: new TestDelegate(), floating: true),
new SliverList(
delegate: new SliverChildListDelegate(<Widget>[
new SizedBox(
height: 300.0,
child: new Text('X'),
),
]),
),
],
),
);
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 200.0));
ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
position.jumpTo(-50.0);
await tester.pump();
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 250.0));
});
}
class TestDelegate extends SliverPersistentHeaderDelegate {

View file

@ -67,6 +67,35 @@ void main() {
Rect rect = new Rect.fromPoints(box.localToGlobal(Point.origin), box.localToGlobal(box.size.bottomRight(Point.origin)));
expect(rect, equals(new Rect.fromLTWH(0.0, -195.0, 800.0, 200.0)));
});
testWidgets('Sliver appbars - scrolling - overscroll gap is below header', (WidgetTester tester) async {
await tester.pumpWidget(
new CustomScrollView(
physics: const BouncingScrollPhysics(),
slivers: <Widget>[
new SliverPersistentHeader(delegate: new TestDelegate()),
new SliverList(
delegate: new SliverChildListDelegate(<Widget>[
new SizedBox(
height: 300.0,
child: new Text('X'),
),
]),
),
],
),
);
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 200.0));
ScrollPosition position = tester.state<ScrollableState>(find.byType(Scrollable)).position;
position.jumpTo(-50.0);
await tester.pump();
expect(tester.getTopLeft(find.byType(Container)), Point.origin);
expect(tester.getTopLeft(find.text('X')), const Point(0.0, 250.0));
});
}
class TestDelegate extends SliverPersistentHeaderDelegate {