mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
SingleChildScrollView can assert in LayoutBuilder (#8162)
We can't read our size in the offset setter because we might be in the middle of layout. This issue also occured with the sliver-based viewport.
This commit is contained in:
parent
70d7fe3a0d
commit
cdc0f15f27
@ -157,7 +157,7 @@ class Scrollable2State extends State<Scrollable2> with TickerProviderStateMixin
|
||||
|
||||
bool _shouldUpdatePosition(Scrollable2 oldConfig) {
|
||||
return config.physics?.runtimeType != oldConfig.physics?.runtimeType
|
||||
|| config.controller?.runtimeType != config.controller?.runtimeType;
|
||||
|| config.controller?.runtimeType != oldConfig.controller?.runtimeType;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -154,24 +154,11 @@ class _RenderSingleChildViewport extends RenderBox with RenderObjectWithChildMix
|
||||
if (value == _offset)
|
||||
return;
|
||||
if (attached)
|
||||
_offset.removeListener(markNeedsLayout);
|
||||
if (_offset.pixels != value.pixels)
|
||||
markNeedsLayout();
|
||||
_offset.removeListener(markNeedsPaint);
|
||||
_offset = value;
|
||||
if (attached)
|
||||
_offset.addListener(markNeedsLayout);
|
||||
// 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 (hasSize) {
|
||||
assert(_minScrollExtent != null);
|
||||
assert(_maxScrollExtent != null);
|
||||
assert(_effectiveExtent != null);
|
||||
final bool didAcceptViewportDimensions = offset.applyViewportDimension(_effectiveExtent);
|
||||
final bool didAcceptContentDimensions = offset.applyContentDimensions(_minScrollExtent, _maxScrollExtent);
|
||||
if (didAcceptViewportDimensions || didAcceptContentDimensions)
|
||||
markNeedsPaint();
|
||||
}
|
||||
_offset.addListener(markNeedsPaint);
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -5,6 +5,32 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class TestScrollPosition extends ScrollPosition {
|
||||
TestScrollPosition({
|
||||
ScrollPhysics physics,
|
||||
AbstractScrollState state,
|
||||
double initialPixels: 0.0,
|
||||
ScrollPosition oldPosition,
|
||||
}) : super(
|
||||
physics: physics,
|
||||
state: state,
|
||||
initialPixels: initialPixels,
|
||||
oldPosition: oldPosition,
|
||||
);
|
||||
}
|
||||
|
||||
class TestScrollController extends ScrollController {
|
||||
@override
|
||||
ScrollPosition createScrollPosition(ScrollPhysics physics, AbstractScrollState state, ScrollPosition oldPosition) {
|
||||
return new TestScrollPosition(
|
||||
physics: physics,
|
||||
state: state,
|
||||
initialPixels: initialScrollOffset,
|
||||
oldPosition: oldPosition,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
testWidgets('SingleChildScrollView control test', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new SingleChildScrollView(
|
||||
@ -23,4 +49,71 @@ void main() {
|
||||
|
||||
expect(box.localToGlobal(Point.origin), equals(const Point(0.0, -200.0)));
|
||||
});
|
||||
|
||||
testWidgets('Changing controllers changes scroll position', (WidgetTester tester) async {
|
||||
TestScrollController controller = new TestScrollController();
|
||||
|
||||
await tester.pumpWidget(new SingleChildScrollView(
|
||||
child: new Container(
|
||||
height: 2000.0,
|
||||
decoration: const BoxDecoration(
|
||||
backgroundColor: const Color(0xFF00FF00),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.pumpWidget(new SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: new Container(
|
||||
height: 2000.0,
|
||||
decoration: const BoxDecoration(
|
||||
backgroundColor: const Color(0xFF00FF00),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
Scrollable2State scrollable = tester.state(find.byType(Scrollable2));
|
||||
expect(scrollable.position, const isInstanceOf<TestScrollPosition>());
|
||||
});
|
||||
|
||||
testWidgets('Changing scroll controller inside dirty layout builder does not assert', (WidgetTester tester) async {
|
||||
ScrollController controller = new ScrollController();
|
||||
|
||||
await tester.pumpWidget(new Center(
|
||||
child: new SizedBox(
|
||||
width: 750.0,
|
||||
child: new LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return new SingleChildScrollView(
|
||||
child: new Container(
|
||||
height: 2000.0,
|
||||
decoration: const BoxDecoration(
|
||||
backgroundColor: const Color(0xFF00FF00),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.pumpWidget(new Center(
|
||||
child: new SizedBox(
|
||||
width: 700.0,
|
||||
child: new LayoutBuilder(
|
||||
builder: (BuildContext context, BoxConstraints constraints) {
|
||||
return new SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: new Container(
|
||||
height: 2000.0,
|
||||
decoration: const BoxDecoration(
|
||||
backgroundColor: const Color(0xFF00FF00),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user