Commit f2ea7304 authored by Adam Barth's avatar Adam Barth Committed by GitHub

PageView shouldn't squish when overscrolled (#7870)

This patch passes down the viewportMainAxisExtent so that RenderSliverPage can
pick it up and size its children appropriately.
parent 332a2303
......@@ -139,6 +139,7 @@ class SliverConstraints extends Constraints {
@required this.overlap,
@required this.remainingPaintExtent,
@required this.crossAxisExtent,
@required this.viewportMainAxisExtent,
});
SliverConstraints copyWith({
......@@ -149,6 +150,7 @@ class SliverConstraints extends Constraints {
double overlap,
double remainingPaintExtent,
double crossAxisExtent,
double viewportMainAxisExtent,
}) {
return new SliverConstraints(
axisDirection: axisDirection ?? this.axisDirection,
......@@ -158,6 +160,7 @@ class SliverConstraints extends Constraints {
overlap: overlap ?? this.overlap,
remainingPaintExtent: remainingPaintExtent ?? this.remainingPaintExtent,
crossAxisExtent: crossAxisExtent ?? this.crossAxisExtent,
viewportMainAxisExtent: viewportMainAxisExtent ?? this.viewportMainAxisExtent,
);
}
......@@ -239,10 +242,16 @@ class SliverConstraints extends Constraints {
/// bottom of a downwards vertical viewport.
final double remainingPaintExtent;
/// The number of pixels in the cross-axis. For a vertical list, this is the
/// width of the viewport.
/// The number of pixels in the cross-axis.
///
/// For a vertical list, this is the width of the sliver..
final double crossAxisExtent;
/// The number of pixels the viewport can display in the main axis.
///
/// For a vertical list, this is the height of the viewport.
final double viewportMainAxisExtent;
Axis get axis => axisDirectionToAxis(axisDirection);
/// Return what the [growthDirection] would be if the [axisDirection] was
......@@ -280,6 +289,7 @@ class SliverConstraints extends Constraints {
bool get isNormalized {
return scrollOffset >= 0.0
&& crossAxisExtent >= 0.0
&& viewportMainAxisExtent >= 0.0
&& remainingPaintExtent >= 0.0;
}
......@@ -320,8 +330,10 @@ class SliverConstraints extends Constraints {
assert(overlap != null);
assert(remainingPaintExtent != null);
assert(crossAxisExtent != null);
assert(viewportMainAxisExtent != null);
assert(scrollOffset >= 0.0);
assert(crossAxisExtent >= 0.0);
assert(viewportMainAxisExtent >= 0.0);
assert(remainingPaintExtent >= 0.0);
assert(isNormalized); // should be redundant with earlier checks
return true;
......@@ -340,12 +352,13 @@ class SliverConstraints extends Constraints {
scrollOffset == typedOther.scrollOffset &&
overlap == typedOther.overlap &&
remainingPaintExtent == typedOther.remainingPaintExtent &&
crossAxisExtent == typedOther.crossAxisExtent;
crossAxisExtent == typedOther.crossAxisExtent &&
viewportMainAxisExtent == typedOther.viewportMainAxisExtent;
}
@override
int get hashCode {
return hashValues(axisDirection, growthDirection, scrollOffset, overlap, remainingPaintExtent, crossAxisExtent);
return hashValues(axisDirection, growthDirection, scrollOffset, overlap, remainingPaintExtent, crossAxisExtent, viewportMainAxisExtent);
}
@override
......@@ -357,7 +370,8 @@ class SliverConstraints extends Constraints {
'scrollOffset: ${scrollOffset.toStringAsFixed(1)}, '
'remainingPaintExtent: ${remainingPaintExtent.toStringAsFixed(1)}, ' +
(overlap != 0.0 ? 'overlap: ${overlap.toStringAsFixed(1)}, ' : '') +
'crossAxisExtent: ${crossAxisExtent.toStringAsFixed(1)}'
'crossAxisExtent: ${crossAxisExtent.toStringAsFixed(1)}' +
'viewportMainAxisExtent: ${viewportMainAxisExtent.toStringAsFixed(1)}' +
')';
}
}
......@@ -1178,6 +1192,7 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
double scrollOffset,
double layoutOffset,
double remainingPaintExtent,
double mainAxisExtent,
double crossAxisExtent,
GrowthDirection growthDirection,
_Advancer advance,
......@@ -1216,6 +1231,7 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
overlap: maxPaintOffset - layoutOffset,
remainingPaintExtent: math.max(0.0, remainingPaintExtent - layoutOffset + initialLayoutOffset),
crossAxisExtent: crossAxisExtent,
viewportMainAxisExtent: mainAxisExtent,
), parentUsesSize: true);
// collect the child's objects
final SliverGeometry childLayoutGeometry = child.geometry;
......@@ -1624,6 +1640,7 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
math.max(mainAxisExtent, mainAxisExtent * anchor - correctedOffset) - mainAxisExtent,
clampedReverseCenter,
clampedForwardCenter,
mainAxisExtent,
crossAxisExtent,
GrowthDirection.reverse,
childBefore,
......@@ -1637,6 +1654,7 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
math.max(0.0, correctedOffset - mainAxisExtent * anchor),
clampedForwardCenter,
clampedReverseCenter,
mainAxisExtent,
crossAxisExtent,
GrowthDirection.forward,
childAfter,
......@@ -1897,6 +1915,7 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont
math.max(0.0, correctedOffset),
0.0,
mainAxisExtent,
mainAxisExtent,
crossAxisExtent,
GrowthDirection.forward,
childAfter,
......
......@@ -148,5 +148,5 @@ class RenderSliverFill extends RenderSliverFixedExtentBoxAdaptor {
}) : super(childManager: childManager);
@override
double get itemExtent => constraints.remainingPaintExtent;
double get itemExtent => constraints.viewportMainAxisExtent;
}
......@@ -25,6 +25,7 @@ void main() {
overlap: 0.0,
remainingPaintExtent: 0.0,
crossAxisExtent: 0.0,
viewportMainAxisExtent: 0.0,
);
SliverConstraints b = a.copyWith();
expect(a, equals(b));
......@@ -41,6 +42,7 @@ void main() {
overlap: 20.0,
remainingPaintExtent: 30.0,
crossAxisExtent: 40.0,
viewportMainAxisExtent: 30.0,
);
SliverConstraints d = new SliverConstraints(
axisDirection: AxisDirection.up,
......@@ -50,6 +52,7 @@ void main() {
overlap: 20.0,
remainingPaintExtent: 30.0,
crossAxisExtent: 40.0,
viewportMainAxisExtent: 30.0,
);
expect(c, equals(d));
expect(c.normalizedGrowthDirection, equals(GrowthDirection.forward));
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'states.dart';
......@@ -73,4 +74,38 @@ void main() {
expect(find.text('Alaska'), findsOneWidget);
expect(find.text('Arizona'), findsNothing);
});
testWidgets('PageView does not squish when overscrolled', (WidgetTester tester) async {
await tester.pumpWidget(new MaterialApp(
theme: new ThemeData(platform: TargetPlatform.iOS),
home: new PageView(
children: new List<Widget>.generate(10, (int i) {
return new Container(
key: new ValueKey<int>(i),
decoration: const BoxDecoration(
backgroundColor: const Color(0xFF0000FF),
),
);
}),
),
));
Size sizeOf(int i) => tester.getSize(find.byKey(new ValueKey<int>(i)));
double leftOf(int i) => tester.getTopLeft(find.byKey(new ValueKey<int>(i))).x;
expect(leftOf(0), equals(0.0));
expect(sizeOf(0), equals(const Size(800.0, 600.0)));
await tester.scroll(find.byType(PageView), const Offset(100.0, 0.0));
await tester.pump();
expect(leftOf(0), equals(100.0));
expect(sizeOf(0), equals(const Size(800.0, 600.0)));
await tester.scroll(find.byType(PageView), const Offset(-200.0, 0.0));
await tester.pump();
expect(leftOf(0), equals(-100.0));
expect(sizeOf(0), equals(const Size(800.0, 600.0)));
});
}
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