Search code examples
flutterexceptiondartflutter-sliver

Error: SliverGeometry has a paintOffset that exceeds the remainingPaintExtent from the constraints


I get this error:

════════ Exception caught by rendering library ═════════════════════════════════
SliverGeometry has a paintOffset that exceeds the remainingPaintExtent from the constraints.
The relevant error-causing widget was
    SliverAppBarLayer

It happens every time I scroll it up. The error is not visible on the screen, only in the console which also prevents me to do hot restart/hot reload. What does it mean? Why does it happen? How to fix it, please?

screenshot

enter image description here

my SliverWidget: sliver_app_bar_layer.dart

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class SliverAppBarLayer extends SingleChildRenderObjectWidget {
  SliverAppBarLayer({Widget child, Key key}) : super(child: child, key: key);
  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderSliverAppBarLayer();
  }
}

class RenderSliverAppBarLayer extends RenderSliverToBoxAdapter {
  RenderSliverAppBarLayer({
    RenderBox child,
  }) : super(child: child);

  @override
  void performResize() {}

  @override
  void performLayout() {
    if (child == null) {
      geometry = SliverGeometry.zero;
      return;
    }
    final SliverConstraints constraints = this.constraints;
    child.layout(constraints.asBoxConstraints(/* crossAxisExtent: double.infinity */), parentUsesSize: true);
    double childExtent;
    switch (constraints.axis) {
      case Axis.horizontal:
        childExtent = child.size.width;
        break;
      case Axis.vertical:
        childExtent = child.size.height;
        break;
    }
    assert(childExtent != null);
    final double paintedChildSize = calculatePaintOffset(constraints, from: 0.0, to: childExtent);
    final double cacheExtent = calculateCacheOffset(constraints, from: 0.0, to: childExtent);

    assert(paintedChildSize.isFinite);
    assert(paintedChildSize >= 0.0);
    geometry = SliverGeometry(
      scrollExtent: 0,
      paintExtent: childExtent,
      paintOrigin: constraints.scrollOffset,
      cacheExtent: cacheExtent,
      maxPaintExtent: childExtent,
      hitTestExtent: paintedChildSize,
    );
    setChildParentData(child, constraints, geometry);
  }
}

main.dart

import 'package:flutter/material.dart';
import 'theme/style_constants.dart';
import 'widgets/sliver_app_bar_layer.dart';

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     theme: ThemeData(
       primarySwatch: Colors.teal,
       canvasColor: Colors.transparent,
     ),
     home: DemoScreen(),
   );
 }
}

class DemoScreen extends StatelessWidget {
 static String id = '/demo';

 int numberOfColumns(dynamic context) => ((MediaQuery.of(context).size.width - (2 * kBigBoxPadding)) / kMaxCrossAxisExtent).floor();

 // Widget _buildGrid() => GridView.extent(
 //     maxCrossAxisExtent: kMaxCrossAxisExtent,
 //     padding: const EdgeInsets.all(4),
 //     mainAxisSpacing: 4,
 //     crossAxisSpacing: 4,
 //     children: _buildGridTileList(500));

 List<Container> _buildGridTileList(dynamic context, int count) => List.generate(
     count,
     (i) => Container(
           //NOTE: workaround according to: https://github.com/flutter/flutter/issues/25009
           decoration: BoxDecoration(
             color: colorBackground, //the color of the main container
             border: Border.all(
               //apply border to only that side where the line is appearing i.e. top | bottom | right | left.
               width: 4, //depends on the width of the unintended line
               color: colorBackground,
             ),
           ),
           child: Container(
             decoration: BoxDecoration(
               color: colorBackground,
             ),

             child: Center(
               child: Text(
                 '$i / ${numberOfColumns(context)}',
                 style: TextStyle(color: Colors.grey),
                 //textAlign: TextAlign.center,
               ),
             ),
             //margin: EdgeInsets.all(0),
           ),
         ));

 // List<Widget> tabbarViewItems() {
 //   List<Widget> items = [];
 //   for (int i = 0; i < 25; i++) {
 //     Widget listView = _buildGrid();
 //     items.add(listView);
 //   }
 //   return items;
 // }

 List<Widget> listViewItems() {
   List<Widget> items = [];

   for (int i = 0; i < 500; i++) {
     Widget widgetItem = Text(
       'item $i',
       textAlign: TextAlign.center,
       style: TextStyle(color: Colors.white),
     );
     items.add(widgetItem);
   }
   return items;
 }

 @override
 Widget build(BuildContext context) {
   return DefaultTabController(
     length: 25,
     child: Scaffold(
       backgroundColor: colorBackground,
       //floatingActionButton: MyTabBar(),
       floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
       body: Stack(
         children: [
           Container(
             width: double.infinity,
             color: Colors.amber,
             child: Image.network(
               'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
               fit: BoxFit.cover,
               height: MediaQuery.of(context).size.height * kCoverHeightProportion,
             ),
             //color: Colors.green,
           ),
           Align(
             alignment: Alignment.bottomCenter,
             child: Container(
               height: 40,
               width: 300,
               color: Colors.red,
             ),
           ),
           Align(
             alignment: Alignment.bottomCenter,
             child: Container(
               margin: EdgeInsets.only(left: kBigBoxPadding, right: kBigBoxPadding, top: kBigBoxPadding, bottom: kBottomBigBoxPadding),

               //width: MediaQuery.of(context).size.width * 0.9,
               //margin: EdgeInsets.symmetric(horizontal: kBigBoxPadding),
               decoration: BoxDecoration(
                 //color: Colors.pink,
                 borderRadius: BorderRadius.all(Radius.circular(30)),
               ),
               child: ClipRRect(
                 borderRadius: BorderRadius.all(Radius.circular(30)),
                 child: CustomScrollView(
                   //physics: FixedExtentScrollPhysics(),
                   anchor: kCoverHeightProportion *
                       kCoverHeightProportion *
                       MediaQuery.of(context).size.height /
                       (kCoverHeightProportion * (MediaQuery.of(context).size.height - kBigBoxPadding - kBottomBigBoxPadding)),
                   slivers: [
                     SliverAppBarLayer(
                       child: Container(
                         width: double.infinity,
                         height: 100,
                         decoration: BoxDecoration(
                             color: colorBackground, borderRadius: BorderRadius.only(topLeft: Radius.circular(30), topRight: Radius.circular(30))),
                         child: Center(
                           child: Text(
                             'La casa de don Juan',
                             style: TextStyle(color: colorPrimary1, fontSize: 32, fontWeight: FontWeight.w800),
                           ),
                         ),
                       ),
                     ),
                     SliverGrid.extent(
                       maxCrossAxisExtent: kMaxCrossAxisExtent,
                       childAspectRatio: 1,
                       mainAxisSpacing: 0,
                       crossAxisSpacing: 0,
                       children: _buildGridTileList(context, 250),
                     ),
                   ],
                 ),
               ),
             ),
           ),
         ],
       ),
     ),
   );
 }
}

style_constants.dart

import 'package:flutter/material.dart';

const Color colorShade1 = Color(0xFFEFF0F2);
const Color colorShade2 = Color(0xFF777777);
const Color colorShade3 = Color(0xFF424242);
const Color colorShade4 = Color(0xFF4B4935);
const Color colorShade5 = Color(0xFF3D2916);
const Color colorShade6 = Color(0xFF1D1C0A);

const Color colorBackground = Color(0xFF101A24);
const Color colorPrimary1 = Color(0xFFCC9757);

const double kTabIconHeight = 28;
const double kCoverHeightProportion = 0.35;
const double kBigBoxPadding = 8;
const double kBottomBigBoxPadding = 60;
const double kMaxCrossAxisExtent = 150;


Solution

  • Just use prepared SliverPersistentHeaderDelegate it works from the box...

    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.teal,
            canvasColor: Colors.transparent,
          ),
          home: DemoScreen(),
        );
      }
    }
    
    class DemoScreen extends StatelessWidget {
      static String id = '/demo';
    
      int numberOfColumns(dynamic context) =>
          ((MediaQuery.of(context).size.width - (2 * kBigBoxPadding)) /
                  kMaxCrossAxisExtent)
              .floor();
    
      // Widget _buildGrid() => GridView.extent(
      //     maxCrossAxisExtent: kMaxCrossAxisExtent,
      //     padding: const EdgeInsets.all(4),
      //     mainAxisSpacing: 4,
      //     crossAxisSpacing: 4,
      //     children: _buildGridTileList(500));
    
      List<Container> _buildGridTileList(dynamic context, int count) =>
          List.generate(
              count,
              (i) => Container(
                    //NOTE: workaround according to: https://github.com/flutter/flutter/issues/25009
                    decoration: BoxDecoration(
                      color: colorBackground, //the color of the main container
                      border: Border.all(
                        //apply border to only that side where the line is appearing i.e. top | bottom | right | left.
                        width: 4, //depends on the width of the unintended line
                        color: colorBackground,
                      ),
                    ),
                    child: Container(
                      decoration: BoxDecoration(
                        color: colorBackground,
                      ),
    
                      child: Center(
                        child: Text(
                          '$i / ${numberOfColumns(context)}',
                          style: TextStyle(color: Colors.grey),
                          //textAlign: TextAlign.center,
                        ),
                      ),
                      //margin: EdgeInsets.all(0),
                    ),
                  ));
    
      // List<Widget> tabbarViewItems() {
      //   List<Widget> items = [];
      //   for (int i = 0; i < 25; i++) {
      //     Widget listView = _buildGrid();
      //     items.add(listView);
      //   }
      //   return items;
      // }
    
      List<Widget> listViewItems() {
        List<Widget> items = [];
    
        for (int i = 0; i < 500; i++) {
          Widget widgetItem = Text(
            'item $i',
            textAlign: TextAlign.center,
            style: TextStyle(color: Colors.white),
          );
          items.add(widgetItem);
        }
        return items;
      }
    
      @override
      Widget build(BuildContext context) {
        var topPadding = kCoverHeightProportion *
            kCoverHeightProportion *
            MediaQuery.of(context).size.height /
            (kCoverHeightProportion *
                (MediaQuery.of(context).size.height -
                    kBigBoxPadding -
                    kBottomBigBoxPadding));
        return DefaultTabController(
          length: 25,
          child: Scaffold(
            backgroundColor: colorBackground,
            //floatingActionButton: MyTabBar(),
            floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
            body: Stack(
              children: [
                Container(
                  width: double.infinity,
                  color: Colors.amber,
                  child: Image.network(
                    'https://images.unsplash.com/photo-1517248135467-4c7edcad34c4?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2700&q=80',
                    fit: BoxFit.cover,
                    height:
                        MediaQuery.of(context).size.height * kCoverHeightProportion,
                  ),
                  //color: Colors.green,
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Container(
                    height: 40,
                    width: 300,
                    color: Colors.red,
                  ),
                ),
                Align(
                  alignment: Alignment.bottomCenter,
                  child: Container(
                    margin: EdgeInsets.only(
                        left: kBigBoxPadding,
                        right: kBigBoxPadding,
                        top: kBigBoxPadding,
                        bottom: kBottomBigBoxPadding),
    
                    //width: MediaQuery.of(context).size.width * 0.9,
                    //margin: EdgeInsets.symmetric(horizontal: kBigBoxPadding),
                    decoration: BoxDecoration(
                      //color: Colors.pink,
                      borderRadius: BorderRadius.all(Radius.circular(30)),
                    ),
                    child: ClipRRect(
                      borderRadius: BorderRadius.all(Radius.circular(30)),
                      child: CustomScrollView(
                        //physics: FixedExtentScrollPhysics(),
                        anchor: topPadding,
                        slivers: [
                          SliverPadding(
                            padding: EdgeInsets.only(
                              top: topPadding,
                            ),
                            sliver: SliverPersistentHeader(
                              pinned: true,
                              floating: false,
                              delegate: _SliverPersistentHeaderDelegate(
                                Container(
                                  width: double.infinity,
                                  height: 100,
                                  decoration: BoxDecoration(
                                      color: colorBackground,
                                      borderRadius: BorderRadius.only(
                                          topLeft: Radius.circular(30),
                                          topRight: Radius.circular(30))),
                                  child: Center(
                                    child: Text(
                                      'La casa de don Juan',
                                      style: TextStyle(
                                          color: colorPrimary1,
                                          fontSize: 32,
                                          fontWeight: FontWeight.w800),
                                    ),
                                  ),
                                ),
                              ),
                            ),
                          ),
                          SliverGrid.extent(
                            maxCrossAxisExtent: kMaxCrossAxisExtent,
                            childAspectRatio: 1,
                            mainAxisSpacing: 0,
                            crossAxisSpacing: 0,
                            children: _buildGridTileList(context, 250),
                          ),
                        ],
                      ),
                    ),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    const Color colorShade1 = Color(0xFFEFF0F2);
    const Color colorShade2 = Color(0xFF777777);
    const Color colorShade3 = Color(0xFF424242);
    const Color colorShade4 = Color(0xFF4B4935);
    const Color colorShade5 = Color(0xFF3D2916);
    const Color colorShade6 = Color(0xFF1D1C0A);
    
    const Color colorBackground = Color(0xFF101A24);
    const Color colorPrimary1 = Color(0xFFCC9757);
    
    const double kTabIconHeight = 28;
    const double kCoverHeightProportion = 0.35;
    const double kBigBoxPadding = 8;
    const double kBottomBigBoxPadding = 60;
    const double kMaxCrossAxisExtent = 150;
    
    class _SliverPersistentHeaderDelegate extends SliverPersistentHeaderDelegate {
      _SliverPersistentHeaderDelegate(this.child);
    
      final Widget child;
    
      @override
      Widget build(
          BuildContext context, double shrinkOffset, bool overlapsContent) {
        return child;
      }
    
      @override
      double get maxExtent => 100;
    
      @override
      double get minExtent => 100;
    
      @override
      bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => false;
    }