fluttercandies / extended_sliver

A powerful extension library of Sliver, which include SliverToNestedScrollBoxAdapter, SliverPinnedPersistentHeader, SliverPinnedToBoxAdapter and ExtendedSliverAppbar.
MIT License
165 stars 30 forks source link

SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent" #10

Closed per-johansson-74 closed 2 years ago

per-johansson-74 commented 2 years ago

When I scroll up/down couple of times that happens, Seems to be a rounding error.

If I comment layoutExtent in line 74 lib/src/rendering.dart so that it uses paintExtent instead the issue seems solved. No more errors and everything seems to work fine for me.

geometry = SliverGeometry(
      scrollExtent: maxExtent,
      paintOrigin: constraints.overlap,
      paintExtent: math.min(childExtent, effectiveRemainingPaintExtent),
      //layoutExtent: layoutExtent,
      maxPaintExtent: maxExtent,
      maxScrollObstructionExtent: minExtent,
      cacheExtent: layoutExtent > 0.0
          ? -constraints.cacheOrigin + layoutExtent
          : layoutExtent,
      hasVisualOverflow:
          true, // Conservatively say we do have overflow to avoid complexity.
    );

Here is couple examples: The paintExtent is 74.6651785714286, but the layoutExtent is 74.66517857142861 The paintExtent is 148.74255952380966, but the layoutExtent is 148.7425595238097

The following assertion was thrown during performLayout():
SliverGeometry is not valid: The "layoutExtent" exceeds the "paintExtent".

The paintExtent is 74.6651785714286, but the layoutExtent is 74.66517857142861.

Maybe you have fallen prey to floating point rounding errors, and should explicitly apply the min() or max() functions, or the clamp() method, to the layoutExtent?

The RenderSliver that returned the offending geometry was: RenderSliverPinnedPersistentHeader#942fa relayoutBoundary=up1 NEEDS-LAYOUT NEEDS-PAINT
...  needs compositing
...  parentData: paintOffset=Offset(0.0, 0.0) (can use size)
...  constraints: SliverConstraints(AxisDirection.down, GrowthDirection.forward, ScrollDirection.reverse, scrollOffset: 85.3, remainingPaintExtent: 547.4, crossAxisExtent: 411.4, crossAxisDirection: AxisDirection.right, viewportMainAxisExtent: 547.4, remainingCacheExtent: 882.8, cacheOrigin: -85.3)
...  geometry: SliverGeometry(scrollExtent: 160.0, paintExtent: 74.7, layoutExtent: 74.7, maxPaintExtent: 160.0, hasVisualOverflow: true, cacheExtent: 160.0)
...    scrollExtent: 160.0
...    paintExtent: 74.7
...    layoutExtent: 74.7
...    maxPaintExtent: 160.0
...    hasVisualOverflow: true
...    cacheExtent: 160.0
...  child position: 0.0
The relevant error-causing widget was: 
  SliverPinnedPersistentHeader SliverPinnedPersistentHeader```

```PS C:\Projekt\app> flutter doctor -v
[√] Flutter (Channel stable, 3.0.0, on Microsoft Windows [Version 10.0.19043.1706], locale sv-SE)
    • Flutter version 3.0.0 at C:\Projekt\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision ee4e09cce0 (4 days ago), 2022-05-09 16:45:18 -0700
    • Engine revision d1b9a6938a
    • Dart version 2.17.0
    • DevTools version 2.12.2

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.0-rc2)
    • Android SDK at C:\Users\blah\AppData\Local\Android\sdk
    • Platform android-31, build-tools 33.0.0-rc2
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version openjdk version "11.0.12" 2021-07-20
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      Download at https://visualstudio.microsoft.com/downloads/.
      Please install the "Desktop development with C++" workload, including all of its default components

[√] Android Studio (version 2021.2)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version openjdk version "11.0.12" 2021-07-20

[√] IntelliJ IDEA Community Edition (version 2021.3)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 12 (API 31) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.19043.1706]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 101.0.4951.54
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 101.0.1210.32

[√] HTTP Host Availability
    • All required HTTP hosts are available
zmtzawqlp commented 2 years ago

It happens in demo on Flutter 3.0.0?

per-johansson-74 commented 2 years ago

I looked more into it. I can not get this error using the example.

I get it when I use animated container in SliverPinnedPersistentHeaderDelegate using final progress = shrinkOffset / maxExtent; and padding: EdgeInsets.lerp( const EdgeInsets.symmetric(horizontal: 16, vertical: 16), const EdgeInsets.symmetric(horizontal: 4, vertical: 4), progress, ),

So I can solve it two ways, remove edgeinsets.lerp from the delegate or comment out layoutExtent: layoutExtent, from the library. I'll just remove the code from delegate that triggers the rounding error in the lib.

(I don't use this for pinning header, I set minExtentProtoType to 0, and maxExtentProtoType i use template so i get the dynamic height of maxExtent, then i put the actual drawn widget in the delegate)

I'll add that if I use same delegate directly in SliverPersistentHeaderDelegate there is no crash due to the floating point rounding.

zmtzawqlp commented 2 years ago

sounds great,it seems a special case with dynamic height,maybe we can make another widget for this case