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,18 +1159,13 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
return;
if (attached)
_offset.removeListener(markNeedsLayout);
if (_offset.pixels != value.pixels)
markNeedsLayout();
_offset = value;
if (attached)
_offset.addListener(markNeedsLayout);
if (hasSize) {
// If we already have a size, then we should re-report the dimensions
// to the new ViewportOffset. If we don't then we'll report them when
// we establish the dimensions later, so don't worry about it now.
if (!rereportDimensions())
markNeedsLayout();
}
// We need to go through layout even if the new offset has the same pixels
// value as the old offset so that we will apply our viewport and content
// dimensions.
markNeedsLayout();
}
@override
......@@ -1506,21 +1501,6 @@ abstract class RenderViewportBase2<ParentDataClass extends ContainerParentDataMi
@protected
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
int indexOfFirstChild();
......@@ -1662,7 +1642,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
if (correction != 0.0) {
offset.correctBy(correction);
} else {
// when updating this, also update rereportDimensions
if (offset.applyContentDimensions(
math.min(0.0, _minScrollExtent + mainAxisExtent * anchor),
math.max(0.0, _maxScrollExtent - mainAxisExtent * (1.0 - anchor)),
......@@ -1822,31 +1801,6 @@ class RenderViewport2 extends RenderViewportBase2<SliverPhysicalContainerParentD
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
int indexOfFirstChild() {
assert(center != null);
......@@ -1994,7 +1948,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont
effectiveExtent = constraints.constrainWidth(_shrinkWrapExtent);
break;
}
// when updating this, also update similar code in rereportDimensions
final bool didAcceptViewportDimension = offset.applyViewportDimension(effectiveExtent);
final bool didAcceptContentDimension = offset.applyContentDimensions(0.0, math.max(0.0, _maxScrollExtent - effectiveExtent));
if (didAcceptViewportDimension && didAcceptContentDimension)
......@@ -2095,24 +2048,6 @@ class RenderShrinkWrappingViewport extends RenderViewportBase2<SliverLogicalCont
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
int indexOfFirstChild() => 0;
......
......@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart' show defaultTargetPlatform;
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart' hide TypeMatcher;
......@@ -12,22 +11,21 @@ class Foo extends StatefulWidget {
}
class FooState extends State<Foo> {
final GlobalKey blockKey = new GlobalKey();
GlobalKey<ScrollableState> scrollableKey = new GlobalKey<ScrollableState>();
ScrollController scrollController = new ScrollController();
@override
Widget build(BuildContext context) {
return new LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
return new ScrollConfiguration(
delegate: new FooScrollConfiguration(),
child: new Block(
scrollableKey: scrollableKey,
return new ScrollConfiguration2(
behavior: new FooScrollBehavior(),
child: new ListView(
controller: scrollController,
children: <Widget>[
new GestureDetector(
onTap: () {
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(
decoration: const BoxDecoration(backgroundColor: const Color(0)),
......@@ -74,25 +72,18 @@ class FooState extends State<Foo> {
}
}
class FooScrollConfiguration extends ScrollConfigurationDelegate {
class FooScrollBehavior extends ScrollBehavior2 {
@override
TargetPlatform get platform => defaultTargetPlatform;
@override
ExtentScrollBehavior createScrollBehavior() =>
new OverscrollWhenScrollableBehavior(platform: platform);
@override
bool updateShouldNotify(FooScrollConfiguration old) => true;
bool shouldNotify(FooScrollBehavior old) => true;
}
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());
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.pump();
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