Fix a bug where ScrollableGrid/ScrollableList would flicker when (#4794)
navigating away. Details are in the bug, but when we navigate away, the overscroll indicator around the Scrollable would change the widget hierarchy. This would trigger the Scrollable to rebuild, which would cause its scrollOffset to be clamped to 0 for a frame. BUG=https://github.com/flutter/flutter/issues/4597
This commit is contained in:
parent
f410ca80b7
commit
6298a1aeb1
@ -226,10 +226,10 @@ class _OverscrollIndicatorState extends State<OverscrollIndicator> {
|
|||||||
child: new AnimatedBuilder(
|
child: new AnimatedBuilder(
|
||||||
animation: _extentAnimation,
|
animation: _extentAnimation,
|
||||||
builder: (BuildContext context, Widget child) {
|
builder: (BuildContext context, Widget child) {
|
||||||
if (_scrollDirection == null) // Haven't seen a scroll yet.
|
// We keep the same widget hierarchy here, even when we're not
|
||||||
return child;
|
// painting anything, to avoid rebuilding the children.
|
||||||
return new CustomPaint(
|
return new CustomPaint(
|
||||||
foregroundPainter: new _Painter(
|
foregroundPainter: _scrollDirection == null ? null : new _Painter(
|
||||||
scrollDirection: _scrollDirection,
|
scrollDirection: _scrollDirection,
|
||||||
extent: _extentAnimation.value,
|
extent: _extentAnimation.value,
|
||||||
isLeading: _scrollOffset < _minScrollOffset,
|
isLeading: _scrollOffset < _minScrollOffset,
|
||||||
|
@ -1610,8 +1610,8 @@ class RenderCustomPaint extends RenderProxyBox {
|
|||||||
markNeedsPaint();
|
markNeedsPaint();
|
||||||
}
|
}
|
||||||
if (attached) {
|
if (attached) {
|
||||||
oldPainter._repaint?.removeListener(markNeedsPaint);
|
oldPainter?._repaint?.removeListener(markNeedsPaint);
|
||||||
newPainter._repaint?.addListener(markNeedsPaint);
|
newPainter?._repaint?.addListener(markNeedsPaint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,14 +50,18 @@ class ClampOverscrolls extends InheritedWidget {
|
|||||||
///
|
///
|
||||||
/// This utility function is typically used by [Scrollable.builder] callbacks.
|
/// This utility function is typically used by [Scrollable.builder] callbacks.
|
||||||
static Widget buildViewport(BuildContext context, ScrollableState state, ViewportBuilder builder) {
|
static Widget buildViewport(BuildContext context, ScrollableState state, ViewportBuilder builder) {
|
||||||
|
// TODO(ianh): minScrollOffset and maxScrollOffset are typically determined
|
||||||
|
// by the container and content size. But we don't know those until we
|
||||||
|
// layout the viewport, which happens after build phase. We need to rethink
|
||||||
|
// this.
|
||||||
final bool clampOverscrolls = ClampOverscrolls.of(context);
|
final bool clampOverscrolls = ClampOverscrolls.of(context);
|
||||||
final double clampedScrollOffset = clampOverscrolls
|
final double clampedScrollOffset = clampOverscrolls
|
||||||
? state.scrollOffset.clamp(state.scrollBehavior.minScrollOffset, state.scrollBehavior.maxScrollOffset)
|
? state.scrollOffset.clamp(state.scrollBehavior.minScrollOffset, state.scrollBehavior.maxScrollOffset)
|
||||||
: state.scrollOffset;
|
: state.scrollOffset;
|
||||||
Widget viewport = builder(context, state, clampedScrollOffset);
|
Widget viewport = builder(context, state, clampedScrollOffset);
|
||||||
if (clampOverscrolls)
|
if (clampOverscrolls)
|
||||||
viewport = new ClampOverscrolls(value: false, child: viewport);
|
viewport = new ClampOverscrolls(value: false, child: viewport);
|
||||||
return viewport;
|
return viewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user