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:
parent
1f7b8ae11f
commit
62cc326a67
@ -209,6 +209,7 @@ abstract class RenderSliverScrollingPersistentHeader extends RenderSliverPersist
|
|||||||
final double paintExtent = maxExtent - constraints.scrollOffset;
|
final double paintExtent = maxExtent - constraints.scrollOffset;
|
||||||
geometry = new SliverGeometry(
|
geometry = new SliverGeometry(
|
||||||
scrollExtent: maxExtent,
|
scrollExtent: maxExtent,
|
||||||
|
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||||
maxPaintExtent: maxExtent,
|
maxPaintExtent: maxExtent,
|
||||||
hasVisualOverflow: true, // Conservatively say we do have overflow to avoid complexity.
|
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;
|
final double layoutExtent = maxExtent - constraints.scrollOffset;
|
||||||
geometry = new SliverGeometry(
|
geometry = new SliverGeometry(
|
||||||
scrollExtent: maxExtent,
|
scrollExtent: maxExtent,
|
||||||
|
paintOrigin: math.min(constraints.overlap, 0.0),
|
||||||
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
paintExtent: paintExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||||
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent),
|
layoutExtent: layoutExtent.clamp(0.0, constraints.remainingPaintExtent),
|
||||||
maxPaintExtent: maxExtent,
|
maxPaintExtent: maxExtent,
|
||||||
|
@ -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));
|
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);
|
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 {
|
class TestDelegate extends SliverPersistentHeaderDelegate {
|
||||||
|
@ -67,6 +67,35 @@ void main() {
|
|||||||
Rect rect = new Rect.fromPoints(box.localToGlobal(Point.origin), box.localToGlobal(box.size.bottomRight(Point.origin)));
|
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)));
|
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 {
|
class TestDelegate extends SliverPersistentHeaderDelegate {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user