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

Port state_setting_in_scrollables_test to Sliver-based scrolling (#8116)

Also fixes a bug when trying to update the offset of a viewport in a layout
builder.

Fixes #8054
parent be865544
...@@ -1159,19 +1159,14 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi ...@@ -1159,19 +1159,14 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
return; return;
if (attached) if (attached)
_offset.removeListener(markNeedsLayout); _offset.removeListener(markNeedsLayout);
if (_offset.pixels != value.pixels)
markNeedsLayout();
_offset = value; _offset = value;
if (attached) if (attached)
_offset.addListener(markNeedsLayout); _offset.addListener(markNeedsLayout);
if (hasSize) { // We need to go through layout even if the new offset has the same pixels
// If we already have a size, then we should re-report the dimensions // value as the old offset so that we will apply our viewport and content
// to the new ViewportOffset. If we don't then we'll report them when // dimensions.
// we establish the dimensions later, so don't worry about it now.
if (!rereportDimensions())
markNeedsLayout(); markNeedsLayout();
} }
}
@override @override
void attach(PipelineOwner owner) { void attach(PipelineOwner owner) {
...@@ -1506,21 +1501,6 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi ...@@ -1506,21 +1501,6 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
@protected @protected
double computeChildMainAxisPosition(RenderSliver child, double parentMainAxisPosition); double computeChildMainAxisPosition(RenderSliver child, double parentMainAxisPosition);
/// Notifies the [offset] of the render object's new dimensions.
///
/// Implementations must call [ViewportOffset.applyViewportDimension] and
/// [ViewportOffset.applyContentDimensions], in that order.
///
/// Return the value returned by [ViewportOffset.applyContentDimensions]:
/// false if the [ViewportOffset] did not accept the new dimensions
/// unconditionally, but instead wants to relayout the render object (e.g.
/// because it changed its mind about the actual offset that the viewport
/// should be laid out at), and true if the [ViewportOffset] was happy with
/// the given dimensions and does not think that anything need change. If this
/// function returns false, the caller will call [markNeedsLayout].
@protected
bool rereportDimensions();
@protected @protected
int indexOfFirstChild(); int indexOfFirstChild();
...@@ -1662,7 +1642,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD ...@@ -1662,7 +1642,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
if (correction != 0.0) { if (correction != 0.0) {
offset.correctBy(correction); offset.correctBy(correction);
} else { } else {
// when updating this, also update rereportDimensions
if (offset.applyContentDimensions( if (offset.applyContentDimensions(
math.min(0.0, _minScrollExtent + mainAxisExtent * anchor), math.min(0.0, _minScrollExtent + mainAxisExtent * anchor),
math.max(0.0, _maxScrollExtent - mainAxisExtent * (1.0 - anchor)), math.max(0.0, _maxScrollExtent - mainAxisExtent * (1.0 - anchor)),
...@@ -1822,31 +1801,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD ...@@ -1822,31 +1801,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
return 0.0; return 0.0;
} }
@override
bool rereportDimensions() {
assert(_minScrollExtent != null);
assert(_maxScrollExtent != null);
assert(anchor != null);
double effectiveExtent;
switch (axis) {
case Axis.vertical:
effectiveExtent = size.height;
break;
case Axis.horizontal:
effectiveExtent = size.width;
break;
}
assert(effectiveExtent != null);
final bool didAcceptViewportDimension = offset.applyViewportDimension(effectiveExtent);
final bool didAcceptContentDimension = offset.applyContentDimensions(
// when updating this, also update similar code in performLayout() and
// performResize().
math.min(0.0, _minScrollExtent + effectiveExtent * anchor),
math.max(0.0, _maxScrollExtent - effectiveExtent * (1.0 - anchor)),
);
return didAcceptViewportDimension && didAcceptContentDimension;
}
@override @override
int indexOfFirstChild() { int indexOfFirstChild() {
assert(center != null); assert(center != null);
...@@ -1994,7 +1948,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont ...@@ -1994,7 +1948,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont
effectiveExtent = constraints.constrainWidth(_shrinkWrapExtent); effectiveExtent = constraints.constrainWidth(_shrinkWrapExtent);
break; break;
} }
// when updating this, also update similar code in rereportDimensions
final bool didAcceptViewportDimension = offset.applyViewportDimension(effectiveExtent); final bool didAcceptViewportDimension = offset.applyViewportDimension(effectiveExtent);
final bool didAcceptContentDimension = offset.applyContentDimensions(0.0, math.max(0.0, _maxScrollExtent - effectiveExtent)); final bool didAcceptContentDimension = offset.applyContentDimensions(0.0, math.max(0.0, _maxScrollExtent - effectiveExtent));
if (didAcceptViewportDimension && didAcceptContentDimension) if (didAcceptViewportDimension && didAcceptContentDimension)
...@@ -2095,24 +2048,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont ...@@ -2095,24 +2048,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont
return 0.0; return 0.0;
} }
@override
bool rereportDimensions() {
assert(_maxScrollExtent != null);
double effectiveExtent;
switch (axis) {
case Axis.vertical:
effectiveExtent = size.height;
break;
case Axis.horizontal:
effectiveExtent = size.width;
break;
}
assert(effectiveExtent != null);
final bool didAcceptViewportDimension = offset.applyViewportDimension(effectiveExtent);
final bool didAcceptContentDimension = offset.applyContentDimensions(0.0, math.max(0.0, _maxScrollExtent - effectiveExtent));
return didAcceptViewportDimension && didAcceptContentDimension;
}
@override @override
int indexOfFirstChild() => 0; int indexOfFirstChild() => 0;
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart' hide TypeMatcher; import 'package:flutter_test/flutter_test.dart' hide TypeMatcher;
...@@ -12,22 +11,21 @@ class Foo extends StatefulWidget { ...@@ -12,22 +11,21 @@ class Foo extends StatefulWidget {
} }
class FooState extends State<Foo> { class FooState extends State<Foo> {
final GlobalKey blockKey = new GlobalKey(); ScrollController scrollController = new ScrollController();
GlobalKey<ScrollableState> scrollableKey = new GlobalKey<ScrollableState>();
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new LayoutBuilder( return new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) { builder: (BuildContext context, BoxConstraints constraints) {
return new ScrollConfiguration( return new ScrollConfiguration2(
delegate: new FooScrollConfiguration(), behavior: new FooScrollBehavior(),
child: new Block( child: new ListView(
scrollableKey: scrollableKey, controller: scrollController,
children: <Widget>[ children: <Widget>[
new GestureDetector( new GestureDetector(
onTap: () { onTap: () {
setState(() { /* this is needed to trigger the original bug this is regression-testing */ }); setState(() { /* this is needed to trigger the original bug this is regression-testing */ });
scrollableKey.currentState.scrollBy(200.0, duration: const Duration(milliseconds: 500)); scrollController.animateTo(200.0, duration: const Duration(milliseconds: 500), curve: Curves.linear);
}, },
child: new DecoratedBox( child: new DecoratedBox(
decoration: const BoxDecoration(backgroundColor: const Color(0)), decoration: const BoxDecoration(backgroundColor: const Color(0)),
...@@ -74,25 +72,18 @@ class FooState extends State<Foo> { ...@@ -74,25 +72,18 @@ class FooState extends State<Foo> {
} }
} }
class FooScrollConfiguration extends ScrollConfigurationDelegate { class FooScrollBehavior extends ScrollBehavior2 {
@override @override
TargetPlatform get platform => defaultTargetPlatform; bool shouldNotify(FooScrollBehavior old) => true;
@override
ExtentScrollBehavior createScrollBehavior() =>
new OverscrollWhenScrollableBehavior(platform: platform);
@override
bool updateShouldNotify(FooScrollConfiguration old) => true;
} }
void main() { void main() {
testWidgets('https://github.com/flutter/flutter/issues/5630', (WidgetTester tester) async { testWidgets('Can animate scroll after setState', (WidgetTester tester) async {
await tester.pumpWidget(new Foo()); await tester.pumpWidget(new Foo());
expect(tester.state<ScrollableState>(find.byType(Scrollable)).scrollOffset, 0.0); expect(tester.state<Scrollable2State>(find.byType(Scrollable2)).position.pixels, 0.0);
await tester.tap(find.byType(GestureDetector).first); await tester.tap(find.byType(GestureDetector).first);
await tester.pump(); await tester.pump();
await tester.pump(const Duration(seconds: 1)); await tester.pump(const Duration(seconds: 1));
expect(tester.state<ScrollableState>(find.byType(Scrollable)).scrollOffset, 200.0); expect(tester.state<Scrollable2State>(find.byType(Scrollable2)).position.pixels, 200.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