Repository: flutter
Issue: [Web]: The "layoutExtent" exceeds the "paintExtent" when animating pinned SliverPersistentHeader
Labels: framework,f: scrolling,has reproducible steps,P2,found in release: 2.1,workaround available,team-framework,triaged-framework

Generally not sure if flutter shall support it, but I am filling, because I suspect it shall be doable.

## Steps to Reproduce

<details>
<summary>Code</summary>

```
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SliverPesistentHeaderScrollUpMouse();
  }
}

class SliverPesistentHeaderScrollUpMouse extends StatefulWidget {

    @override
  _SliverPesistentHeaderScrollUpMouseState createState() => _SliverPesistentHeaderScrollUpMouseState();
  
}
class _SliverPesistentHeaderScrollUpMouseState extends State<SliverPesistentHeaderScrollUpMouse> with SingleTickerProviderStateMixin {

  AnimationController _animationController;
  final _scrollController = ScrollController();
  Animation<double> _sizeAnimation;

  @override
  void initState() {
    super.initState();

    _animationController = AnimationController(
      duration: Duration(milliseconds: 300), 
      vsync: this
    );

    _sizeAnimation = CurvedAnimation(
      parent: _animationController,
      curve: Curves.fastOutSlowIn,
    );

    _animationController.value = _animationController.upperBound;

    _scrollController.addListener(() {
      if (_scrollController.position.userScrollDirection == ScrollDirection.forward) {
        _animationController.forward();
      }  else {
        _animationController.reverse();
      }
      });
  }
  
  @override
  Widget build(BuildContext context) {
    List<Widget> _widgets = [];
    for (int i = 0; i < 200; i++) {
      _widgets.add(
        Container(
          height: 20,
          color: Colors.blue,
          child: Center(
            child: Text(i.toString()),
          )
        )
      );
    }
    return MaterialApp(
      title: 'Default label',
      home: Scaffold(
        body: CustomScrollView(
          controller: _scrollController,
          slivers: [
            SliverPersistentHeader(
              pinned: true,
              delegate: Header(_sizeAnimation),
            ),
            SliverList(
              delegate: SliverChildListDelegate(
                _widgets
              ),
            )
          ],
        )
      )
    );
  }
}

class Header extends SliverPersistentHeaderDelegate {

  final Animation<double> _sizeAnimation;

  Header(Animation<double> sizeAnimation) :
    _sizeAnimation = sizeAnimation;

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return SizeTransition(
      sizeFactor: _sizeAnimation,
      child: Container(
        height: 50,
        color: Colors.red,
      )
    );
  }

  @override
  double get maxExtent => 50;

  @override
  double get minExtent => 50;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
    return false;
  }
}
```

</details>

**Expected results:** <!-- what did you want to see? -->

No exception.

**Actual results:** <!-- what did you see? -->

In case of fast scrolling from the very top to bottom. This is **crucial** - when the scrolling is in the middle of page, then fast scrolling up and down has no exception, but when fast scrolling is from the very beginning to bottom direction (or to be sure - fast jumping between beginning of the page to bottom to just "execute" animation) then exception is thrown.

It looks like the problem is with rendering when animation does not complete (for instance, below exception was thrown when paintExtent == sizeAnimation.value * layoutExtent).

<details>
  <summary>Logs</summary>

```
══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following assertion was thrown during performLayout():
SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent".
The paintExtent is 48.4, but the layoutExtent is 50.0.
The RenderSliver that returned the offending geometry was: _RenderSliverPinnedPersistentHeaderForWidgets#4efaf relayoutBoundary=up1:
  creator: _SliverPinnedPersistentHeader ← SliverPersistentHeader ← Viewport ←
    IgnorePointer-[GlobalKey#8f785] ← Semantics ← Listener ← _GestureSemantics ←
    RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#53e12] ← Listener ← _ScrollableScope
    ← _ScrollSemantics-[GlobalKey#8b870] ← Scrollable ← ⋯
  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle,
    scrollOffset: 0.0, remainingPaintExtent: 969.0, crossAxisExtent: 1920.0, crossAxisDirection:
    AxisDirection.right, viewportMainAxisExtent: 969.0, remainingCacheExtent: 1219.0, cacheOrigin:
    0.0)
  geometry: SliverGeometry(scrollExtent: 50.0, paintExtent: 48.4, layoutExtent: 50.0, maxPaintExtent:
    50.0, hasVisualOverflow: true, cacheExtent: 50.0)
  maxExtent: 50.0
  child position: 0.0

The following RenderObject was being processed when the exception was fired: _RenderSliverPinnedPersistentHeaderForWidgets#4efaf relayoutBoundary=up1:
  creator: _SliverPinnedPersistentHeader ← SliverPersistentHeader ← Viewport ←
    IgnorePointer-[GlobalKey#8f785] ← Semantics ← Listener ← _GestureSemantics ←
    RawGestureDetector-[LabeledGlobalKey<RawGestureDetectorState>#53e12] ← Listener ← _ScrollableScope
    ← _ScrollSemantics-[GlobalKey#8b870] ← Scrollable ← ⋯
  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.idle,
    scrollOffset: 0.0, remainingPaintExtent: 969.0, crossAxisExtent: 1920.0, crossAxisDirection:
    AxisDirection.right, viewportMainAxisExtent: 969.0, remainingCacheExtent: 1219.0, cacheOrigin:
    0.0)
  geometry: SliverGeometry(scrollExtent: 50.0, paintExtent: 48.4, layoutExtent: 50.0, maxPaintExtent:
    50.0, hasVisualOverflow: true, cacheExtent: 50.0)
  maxExtent: 50.0
  child position: 0.0
This RenderObject had the following descendants (showing up to depth 5):
    child: RenderClipRect#749d6 relayoutBoundary=up2
      child: RenderPositionedBox#c412b relayoutBoundary=up3
        child: RenderConstrainedBox#7a930 relayoutBoundary=up4
          child: _RenderColoredBox#c4722 relayoutBoundary=up5
            child: RenderLimitedBox#db1f5 relayoutBoundary=up6

```
</details>

<details>
<summary>Doctor</summary>

```
[√] Flutter (Channel stable, 2.0.0, on Microsoft Windows [Version 10.0.19041.867], locale pl-PL)
    • Flutter version 2.0.0 at G:\IOT\flutter\flutter
    • Framework revision 60bd88df91 (3 weeks ago), 2021-03-03 09:13:17 -0800
    • Engine revision 40441def69
    • Dart version 2.12.0

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at C:\Users\Radek\AppData\Local\Android\sdk
    • Platform android-29, build-tools 29.0.2
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 3.5)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 39.0.3
    • Dart plugin version 191.8423
    • Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b03)

[√] Connected device (2 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 89.0.4389.90
    • Edge (web)   • edge   • web-javascript • Microsoft Edge 88.0.705.74
```

</details>