Unverified Commit 851d6996 authored by LongCatIsLooong's avatar LongCatIsLooong Committed by GitHub

Revert "Implement PageView using SliverLayoutBuilder, Deprecate...

Revert "Implement PageView using SliverLayoutBuilder, Deprecate RenderSliverFillViewport (#37024)" (#44778)

* Revert "Implement PageView using SliverLayoutBuilder, Deprecate RenderSliverFillViewport (#37024)"

This reverts commit 9aea03f4.
parent f48f4573
...@@ -27,7 +27,6 @@ import 'sliver_multi_box_adaptor.dart'; ...@@ -27,7 +27,6 @@ import 'sliver_multi_box_adaptor.dart';
/// * [RenderSliverFixedExtentList], which has a configurable [itemExtent]. /// * [RenderSliverFixedExtentList], which has a configurable [itemExtent].
/// * [RenderSliverList], which does not require its children to have the same /// * [RenderSliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
@Deprecated('Use SliverLayoutBuilder instead.')
class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor { class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor {
/// Creates a sliver that contains multiple box children that each fill the /// Creates a sliver that contains multiple box children that each fill the
/// viewport. /// viewport.
...@@ -106,6 +105,8 @@ class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor { ...@@ -106,6 +105,8 @@ class RenderSliverFillViewport extends RenderSliverFixedExtentBoxAdaptor {
/// ///
/// See also: /// See also:
/// ///
/// * [RenderSliverFillViewport], which sizes its children based on the
/// size of the viewport, regardless of what else is in the scroll view.
/// * [RenderSliverList], which shows a list of variable-sized children in a /// * [RenderSliverList], which shows a list of variable-sized children in a
/// viewport. /// viewport.
class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter { class RenderSliverFillRemaining extends RenderSliverSingleBoxAdapter {
......
...@@ -345,16 +345,8 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri ...@@ -345,16 +345,8 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri
forcePixels(getPixelsFromPage(oldPage)); forcePixels(getPixelsFromPage(oldPage));
} }
// The amount of offset that will be added to [minScrollExtent] and subtracted
// from [maxScrollExtent], such that every page will properly snap to the center
// of the viewport when viewportFraction is greater than 1.
//
// The value is 0 if viewportFraction is less than or equal to 1, larger than 0
// otherwise.
double get _initialPageOffset => math.max(0, viewportDimension * (viewportFraction - 1) / 2);
double getPageFromPixels(double pixels, double viewportDimension) { double getPageFromPixels(double pixels, double viewportDimension) {
final double actual = math.max(0, pixels - _initialPageOffset) / math.max(1.0, viewportDimension * viewportFraction); final double actual = math.max(0.0, pixels) / math.max(1.0, viewportDimension * viewportFraction);
final double round = actual.roundToDouble(); final double round = actual.roundToDouble();
if ((actual - round).abs() < precisionErrorTolerance) { if ((actual - round).abs() < precisionErrorTolerance) {
return round; return round;
...@@ -363,7 +355,7 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri ...@@ -363,7 +355,7 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri
} }
double getPixelsFromPage(double page) { double getPixelsFromPage(double page) {
return page * viewportDimension * viewportFraction + _initialPageOffset; return page * viewportDimension * viewportFraction;
} }
@override @override
...@@ -404,15 +396,6 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri ...@@ -404,15 +396,6 @@ class _PagePosition extends ScrollPositionWithSingleContext implements PageMetri
return result; return result;
} }
@override
bool applyContentDimensions(double minScrollExtent, double maxScrollExtent) {
final double newMinScrollExtent = minScrollExtent + _initialPageOffset;
return super.applyContentDimensions(
newMinScrollExtent,
math.max(newMinScrollExtent, maxScrollExtent - _initialPageOffset),
);
}
@override @override
PageMetrics copyWith({ PageMetrics copyWith({
double minScrollExtent, double minScrollExtent,
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:collection' show SplayTreeMap, HashMap; import 'dart:collection' show SplayTreeMap, HashMap;
import 'dart:math' as math show max;
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
...@@ -11,7 +10,6 @@ import 'package:flutter/rendering.dart'; ...@@ -11,7 +10,6 @@ import 'package:flutter/rendering.dart';
import 'automatic_keep_alive.dart'; import 'automatic_keep_alive.dart';
import 'basic.dart'; import 'basic.dart';
import 'framework.dart'; import 'framework.dart';
import 'sliver_layout_builder.dart';
export 'package:flutter/rendering.dart' show export 'package:flutter/rendering.dart' show
SliverGridDelegate, SliverGridDelegate,
...@@ -727,7 +725,6 @@ abstract class SliverMultiBoxAdaptorWidget extends SliverWithKeepAliveWidget { ...@@ -727,7 +725,6 @@ abstract class SliverMultiBoxAdaptorWidget extends SliverWithKeepAliveWidget {
}) : assert(delegate != null), }) : assert(delegate != null),
super(key: key); super(key: key);
/// {@template flutter.widgets.sliverChildDelegate}
/// The delegate that provides the children for this widget. /// The delegate that provides the children for this widget.
/// ///
/// The children are constructed lazily using this delegate to avoid creating /// The children are constructed lazily using this delegate to avoid creating
...@@ -738,7 +735,6 @@ abstract class SliverMultiBoxAdaptorWidget extends SliverWithKeepAliveWidget { ...@@ -738,7 +735,6 @@ abstract class SliverMultiBoxAdaptorWidget extends SliverWithKeepAliveWidget {
/// * [SliverChildBuilderDelegate] and [SliverChildListDelegate], which are /// * [SliverChildBuilderDelegate] and [SliverChildListDelegate], which are
/// commonly used subclasses of [SliverChildDelegate] that use a builder /// commonly used subclasses of [SliverChildDelegate] that use a builder
/// callback and an explicit child list, respectively. /// callback and an explicit child list, respectively.
/// {@endtemplate}
final SliverChildDelegate delegate; final SliverChildDelegate delegate;
@override @override
...@@ -1042,16 +1038,15 @@ class SliverGrid extends SliverMultiBoxAdaptorWidget { ...@@ -1042,16 +1038,15 @@ class SliverGrid extends SliverMultiBoxAdaptorWidget {
/// the main axis extent of each item. /// the main axis extent of each item.
/// * [SliverList], which does not require its children to have the same /// * [SliverList], which does not require its children to have the same
/// extent in the main axis. /// extent in the main axis.
class SliverFillViewport extends StatelessWidget { class SliverFillViewport extends SliverMultiBoxAdaptorWidget {
/// Creates a sliver whose box children that each fill the viewport. /// Creates a sliver whose box children that each fill the viewport.
const SliverFillViewport({ const SliverFillViewport({
Key key, Key key,
@required this.delegate, @required SliverChildDelegate delegate,
this.viewportFraction = 1.0, this.viewportFraction = 1.0,
}) : assert(viewportFraction != null), }) : assert(viewportFraction != null),
assert(viewportFraction > 0.0), assert(viewportFraction > 0.0),
assert(delegate != null), super(key: key, delegate: delegate);
super(key: key);
/// The fraction of the viewport that each child should fill in the main axis. /// The fraction of the viewport that each child should fill in the main axis.
/// ///
...@@ -1060,34 +1055,15 @@ class SliverFillViewport extends StatelessWidget { ...@@ -1060,34 +1055,15 @@ class SliverFillViewport extends StatelessWidget {
/// the viewport in the main axis. /// the viewport in the main axis.
final double viewportFraction; final double viewportFraction;
/// {@macro flutter.widgets.sliverChildDelegate}
final SliverChildDelegate delegate;
@override @override
Widget build(BuildContext context) { RenderSliverFillViewport createRenderObject(BuildContext context) {
return SliverLayoutBuilder( final SliverMultiBoxAdaptorElement element = context;
builder: (BuildContext context, SliverConstraints constraints) { return RenderSliverFillViewport(childManager: element, viewportFraction: viewportFraction);
final double fixedExtent = constraints.viewportMainAxisExtent * viewportFraction; }
final double padding = math.max(0, constraints.viewportMainAxisExtent - fixedExtent) / 2;
EdgeInsets sliverPaddingValue;
switch (constraints.axis) {
case Axis.horizontal:
sliverPaddingValue = EdgeInsets.symmetric(horizontal: padding);
break;
case Axis.vertical:
sliverPaddingValue = EdgeInsets.symmetric(vertical: padding);
}
return SliverPadding( @override
padding: sliverPaddingValue, void updateRenderObject(BuildContext context, RenderSliverFillViewport renderObject) {
sliver: SliverFixedExtentList( renderObject.viewportFraction = viewportFraction;
delegate: delegate,
itemExtent: fixedExtent,
),
);
}
);
} }
} }
......
...@@ -24,7 +24,7 @@ void main() { ...@@ -24,7 +24,7 @@ void main() {
offset: ViewportOffset.zero(), offset: ViewportOffset.zero(),
cacheExtent: 0, cacheExtent: 0,
children: <RenderSliver>[ children: <RenderSliver>[
childManager.createRenderSliverFixedExtentList(), childManager.createRenderSliverFillViewport(),
], ],
); );
layout(root); layout(root);
...@@ -52,11 +52,10 @@ class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager { ...@@ -52,11 +52,10 @@ class TestRenderSliverBoxChildManager extends RenderSliverBoxChildManager {
RenderSliverMultiBoxAdaptor _renderObject; RenderSliverMultiBoxAdaptor _renderObject;
List<RenderBox> children; List<RenderBox> children;
RenderSliverFixedExtentList createRenderSliverFixedExtentList() { RenderSliverFillViewport createRenderSliverFillViewport() {
assert(_renderObject == null); assert(_renderObject == null);
_renderObject = RenderSliverFixedExtentList( _renderObject = RenderSliverFillViewport(
childManager: this, childManager: this,
itemExtent: 600,
); );
return _renderObject; return _renderObject;
} }
......
...@@ -601,52 +601,6 @@ void main() { ...@@ -601,52 +601,6 @@ void main() {
expect(tester.getTopLeft(find.text('Hawaii')), const Offset(-(4 - 1) * 800 / 2, 0)); expect(tester.getTopLeft(find.text('Hawaii')), const Offset(-(4 - 1) * 800 / 2, 0));
}); });
testWidgets(
'All visible pages are able to receive touch events',
(WidgetTester tester) async {
final PageController controller = PageController(viewportFraction: 1/4, initialPage: 0);
int tappedIndex;
Widget build() {
return Directionality(
textDirection: TextDirection.ltr,
child: PageView.builder(
controller: controller,
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return GestureDetector(
onTap: () => tappedIndex = index,
child: SizedBox.expand(child: Text('$index')),
);
},
),
);
}
Iterable<int> visiblePages = const <int> [0, 1, 2];
await tester.pumpWidget(build());
// The first 3 items should be visible and tappable.
for (int index in visiblePages) {
expect(find.text(index.toString()), findsOneWidget);
// The center of page 2's x-coordinate is 800, so we have to manually
// offset it a bit to make sure the tap lands within the screen.
final Offset center = tester.getCenter(find.text('$index')) - const Offset(3, 0);
await tester.tapAt(center);
expect(tappedIndex, index);
}
controller.jumpToPage(19);
await tester.pump();
// The last 3 items should be visible and tappable.
visiblePages = const <int> [17, 18, 19];
for (int index in visiblePages) {
expect(find.text('$index'), findsOneWidget);
await tester.tap(find.text('$index'));
expect(tappedIndex, index);
}
});
testWidgets('PageView does not report page changed on overscroll', (WidgetTester tester) async { testWidgets('PageView does not report page changed on overscroll', (WidgetTester tester) async {
final PageController controller = PageController( final PageController controller = PageController(
initialPage: kStates.length - 1, initialPage: kStates.length - 1,
......
...@@ -64,7 +64,7 @@ void main() { ...@@ -64,7 +64,7 @@ void main() {
expect( expect(
viewport.toStringDeep(minLevel: DiagnosticLevel.info), viewport.toStringDeep(minLevel: DiagnosticLevel.info),
equalsIgnoringHashCodes( equalsIgnoringHashCodes(
'_RenderSliverLayoutBuilder#00000 relayoutBoundary=up1\n' 'RenderSliverFillViewport#00000 relayoutBoundary=up1\n'
' │ needs compositing\n' ' │ needs compositing\n'
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n' ' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n' ' │ constraints: SliverConstraints(AxisDirection.down,\n'
...@@ -76,86 +76,58 @@ void main() { ...@@ -76,86 +76,58 @@ void main() {
' │ geometry: SliverGeometry(scrollExtent: 12000.0, paintExtent:\n' ' │ geometry: SliverGeometry(scrollExtent: 12000.0, paintExtent:\n'
' │ 600.0, maxPaintExtent: 12000.0, hasVisualOverflow: true,\n' ' │ 600.0, maxPaintExtent: 12000.0, hasVisualOverflow: true,\n'
' │ cacheExtent: 850.0)\n' ' │ cacheExtent: 850.0)\n'
' │ currently live children: 0 to 1\n'
' │\n' ' │\n'
' └─child: RenderSliverPadding#00000 relayoutBoundary=up2\n' ' ├─child with index 0: RenderRepaintBoundary#00000\n'
' │ │ needs compositing\n'
' │ │ parentData: index=0; layoutOffset=0.0\n'
' │ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ │ layer: OffsetLayer#00000\n'
' │ │ size: Size(800.0, 600.0)\n'
' │ │ metrics: 66.7% useful (1 bad vs 2 good)\n'
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
' │ └─child: RenderParagraph#00000\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ │ semantics node: SemanticsNode#2\n'
' │ │ size: Size(800.0, 600.0)\n'
' │ │ textAlign: start\n'
' │ │ textDirection: ltr\n'
' │ │ softWrap: wrapping at box width\n'
' │ │ overflow: clip\n'
' │ │ maxLines: unlimited\n'
' │ ╘═╦══ text ═══\n'
' │ ║ TextSpan:\n'
' │ ║ <all styles inherited>\n'
' │ ║ "0"\n'
' │ ╚═══════════\n'
' └─child with index 1: RenderRepaintBoundary#00000\n'
' │ needs compositing\n' ' │ needs compositing\n'
' │ parentData: <none> (can use size)\n' ' │ parentData: index=1; layoutOffset=600.0\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n' ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' ' │ layer: OffsetLayer#00000 DETACHED\n'
' │ 0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n' ' │ size: Size(800.0, 600.0)\n'
' │ crossAxisDirection: AxisDirection.right,\n' ' │ metrics: 50.0% useful (1 bad vs 1 good)\n'
' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0\n' ' │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ cacheOrigin: 0.0 )\n' ' │ repaints)\n'
' │ geometry: SliverGeometry(scrollExtent: 12000.0, paintExtent:\n'
' │ 600.0, maxPaintExtent: 12000.0, hasVisualOverflow: true,\n'
' │ cacheExtent: 850.0)\n'
' │ padding: EdgeInsets.zero\n'
' │ textDirection: ltr\n'
' │\n' ' │\n'
' └─child: RenderSliverFixedExtentList#00000 relayoutBoundary=up3\n' ' └─child: RenderParagraph#00000\n'
' │ needs compositing\n' ' │ parentData: <none> (can use size)\n'
' │ parentData: paintOffset=Offset(0.0, 0.0) (can use size)\n' ' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ constraints: SliverConstraints(AxisDirection.down,\n' ' │ semantics node: SemanticsNode#3\n'
' │ GrowthDirection.forward, ScrollDirection.idle, scrollOffset:\n' ' │ size: Size(800.0, 600.0)\n'
' │ 0.0, remainingPaintExtent: 600.0, crossAxisExtent: 800.0,\n' ' │ textAlign: start\n'
' │ crossAxisDirection: AxisDirection.right,\n' ' │ textDirection: ltr\n'
' │ viewportMainAxisExtent: 600.0, remainingCacheExtent: 850.0\n' ' │ softWrap: wrapping at box width\n'
' │ cacheOrigin: 0.0 )\n' ' │ overflow: clip\n'
' │ geometry: SliverGeometry(scrollExtent: 12000.0, paintExtent:\n' ' │ maxLines: unlimited\n'
' │ 600.0, maxPaintExtent: 12000.0, hasVisualOverflow: true,\n' ' ╘═╦══ text ═══\n'
' │ cacheExtent: 850.0)\n' ' ║ TextSpan:\n'
' │ currently live children: 0 to 1\n' ' ║ <all styles inherited>\n'
' │\n' ' ║ "1"\n'
' ├─child with index 0: RenderRepaintBoundary#00000\n' ' ╚═══════════\n'
' │ │ needs compositing\n'
' │ │ parentData: index=0; layoutOffset=0.0\n'
' │ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ │ layer: OffsetLayer#00000\n'
' │ │ size: Size(800.0, 600.0)\n'
' │ │ metrics: 66.7% useful (1 bad vs 2 good)\n'
' │ │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ │ repaints)\n'
' │ │\n'
' │ └─child: RenderParagraph#00000\n'
' │ │ parentData: <none> (can use size)\n'
' │ │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ │ semantics node: SemanticsNode#2\n'
' │ │ size: Size(800.0, 600.0)\n'
' │ │ textAlign: start\n'
' │ │ textDirection: ltr\n'
' │ │ softWrap: wrapping at box width\n'
' │ │ overflow: clip\n'
' │ │ maxLines: unlimited\n'
' │ ╘═╦══ text ═══\n'
' │ ║ TextSpan:\n'
' │ ║ <all styles inherited>\n'
' │ ║ "0"\n'
' │ ╚═══════════\n'
' └─child with index 1: RenderRepaintBoundary#00000\n'
' │ needs compositing\n'
' │ parentData: index=1; layoutOffset=600.0\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ layer: OffsetLayer#00000 DETACHED\n'
' │ size: Size(800.0, 600.0)\n'
' │ metrics: 50.0% useful (1 bad vs 1 good)\n'
' │ diagnosis: insufficient data to draw conclusion (less than five\n'
' │ repaints)\n'
' │\n'
' └─child: RenderParagraph#00000\n'
' │ parentData: <none> (can use size)\n'
' │ constraints: BoxConstraints(w=800.0, h=600.0)\n'
' │ semantics node: SemanticsNode#3\n'
' │ size: Size(800.0, 600.0)\n'
' │ textAlign: start\n'
' │ textDirection: ltr\n'
' │ softWrap: wrapping at box width\n'
' │ overflow: clip\n'
' │ maxLines: unlimited\n'
' ╘═╦══ text ═══\n'
' ║ TextSpan:\n'
' ║ <all styles inherited>\n'
' ║ "1"\n'
' ╚═══════════\n'
'' ''
), ),
); );
......
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