Search code examples
flutterdartlayoutoverflowflutter-renderflex-error

Fixing RenderFlex Overflow Error in Flutter ToDo App


I'm developing a ToDo app using Flutter and encountered a RenderFlex overflowed error that I'm struggling to resolve. The debug console provided the following output, indicating that the contents of a RenderFlex widget are too big to fit within the available space:

The overflowing RenderFlex has an orientation of Axis.vertical. The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and black striped pattern. This is usually caused by the contents being too big for the RenderFlex. Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size. This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView. The specific RenderFlex in question is: RenderFlex#33d4b relayoutBoundary=up2 OVERFLOWING: needs compositing creator: Column ← MediaQuery ← Padding ← SafeArea ← Stack ← LayoutBuilder ← SizedBox ← Center ← KeyedSubtree-[GlobalKey#bf933] ← _BodyBuilder ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← ⋯ parentData: offset=Offset(0.0, 0.0) (can use size) constraints: BoxConstraints(0.0<=w<=500.0, 0.0<=h<=237.0) size: Size(500.0, 237.0) direction: vertical

I've isolated the issue to my ToDoPage widget, where a Column widget containing several child widgets, including text and images, seems to be the source of the problem. Below is the relevant portion of my code:


class ToDoPage extends StatefulWidget {
  const ToDoPage({Key? key}) : super(key: key);

  @override
  State<ToDoPage> createState() => _ToDoPageState();
}

class _ToDoPageState extends State<ToDoPage> {
  bool isActive = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xffFAFAFA),
      body: Center(
        child: SizedBox(
          height: MediaQuery.of(context).size.height,
          width: MediaQuery.of(context).size.width,
          child: LayoutBuilder(
            builder: (context, constraints) => Stack(
              children: [
                SizedBox(
                  height: MediaQuery.of(context).size.height,
                  width: MediaQuery.of(context).size.width,
                  child: Image.asset(
                    "assets/mountain.jpg",
                    fit: BoxFit.cover,
                  ),
                ),
                SafeArea(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.stretch,
                    children: [
                      const SizedBox(
                        height: 20.0,
                      ),
                      Row(
                        mainAxisAlignment: MainAxisAlignment.spaceBetween,
                        children: [
                          Expanded(
                            child: Padding(
                              padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                              child: Align(
                                alignment: Alignment.topLeft,
                                child: Text(
                                  'My success list',
                                  style: GoogleFonts.nunito(
                                    color: Colors.white,
                                    fontSize: 30.0,
                                    fontWeight: FontWeight.w500,
                                  ),
                                ),
                              ),
                            ),
                          ),
                          Padding(
                            padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                            child: Tooltip(
                              message: 'List options menu',
                              child: Semantics(
                                label: 'My success list options menu',
                                enabled: true,
                                readOnly: true,
                                child: IconButton(
                                  icon: const Icon(
                                    Icons.more_vert_outlined,
                                    color: Colors.white,
                                    size: 25,
                                    semanticLabel:
                                        'Pomodoro timer list options menu',
                                  ),
                                  onPressed: () {
                                    Navigator.push(
                                      context,
                                      MaterialPageRoute(
                                          builder: (context) =>
                                              Text('list options menu')),
                                    );
                                  },
                                ),
                              ),
                            ),
                          ),
                        ],
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                        child: Align(
                          alignment: Alignment.topLeft,
                          child: Text(
                            'Thusrday, December 29, 2022',
                            style: GoogleFonts.nunito(
                              color: Colors.white,
                              fontSize: 20.0,
                              fontWeight: FontWeight.w500,
                            ),
                          ),
                        ),
                      ),
                      Padding(
                        padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                        child: Align(
                          alignment: Alignment.center,
                          child: Glassmorphism(
                            blur: 5,
                            opacity: 0.2,
                            radius: 15,
                            child: Container(
                              height: 100,
                              padding: const EdgeInsets.all(8),
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.stretch,
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceAround,
                                children: [
                                  Row(
                                    mainAxisAlignment:
                                        MainAxisAlignment.spaceBetween,
                                    children: [
                                      Text(
                                        'task 1',
                                        style: GoogleFonts.nunito(
                                          color: Colors.white,
                                          fontSize: 24.0,
                                          fontWeight: FontWeight.bold,
                                        ),
                                      ),
                                      SmileFaceCheckbox(
                                          isActive: isActive,
                                          onPress: () {
                                            setState(() {
                                              isActive = !isActive;
                                            });
                                          }),
                                    ],
                                  ),
                                  Align(
                                    alignment: Alignment.topLeft,
                                    child: Text(
                                      'Explain note',
                                      textAlign: TextAlign.center,
                                      style: GoogleFonts.nunito(
                                        color: Colors.white.withOpacity(0.8),
                                        fontSize: 16.0,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ),
                      //hiint
                      Expanded(
                        child: Align(
                          alignment: FractionalOffset.bottomCenter,
                          child: SingleChildScrollView(
                            child: Column(
                              crossAxisAlignment: CrossAxisAlignment.stretch,
                              mainAxisAlignment: MainAxisAlignment.end,
                              children: [
                                Padding(
                                  padding: const EdgeInsets.symmetric(
                                      vertical: 10.0, horizontal: 15.0),
                                  child: Glassmorphism(
                                    blur: 20,
                                    opacity: 0.1,
                                    radius: 15.0,
                                    child: TextButton(
                                      onPressed: () {
                                        // handle push to HomeScreen
                                      },
                                      child: Container(
                                        padding: const EdgeInsets.symmetric(
                                          vertical: 10.0,
                                          horizontal: 15.0,
                                        ),
                                        child: Text(
                                          '+ Add successful task',
                                          style: GoogleFonts.nunito(
                                            color: Colors.white,
                                            fontSize: 20.0,
                                          ),
                                        ),
                                      ),
                                    ),
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

In an attempt to fix the issue, I've tried wrapping the problematic Column widget in a SingleChildScrollView and using Expanded widgets around my text widgets, but the overflow error persists.

Here's a snippet of the attempted fix:

SafeArea(
  child: Expanded(
    child: SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          const SizedBox(height: 20.0),
         
        ],
      ),
    ),
  ),
)

And for the text widgets:


child: Flexible(
  child: Text(
    'My success list',
    style: GoogleFonts.nunito(
      color: Colors.white,
      fontSize: 30.0,
      fontWeight: FontWeight.w500,
    ),
  ),
)




I've also included custom widgets Glassmorphism and SmileFaceCheckbox in my UI. Could these be affecting layout calculations?

Update:

Glassmorphism.dart

  import 'dart:ui';
    
    import 'package:flutter/material.dart';
    
    class Glassmorphism extends StatelessWidget {
      final double blur;
      final double opacity;
      final double radius;
      final Widget child;
    
      const Glassmorphism({
        Key? key,
        required this.blur,
        required this.opacity,
        required this.radius,
        required this.child,
      }) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return ClipRRect(
          borderRadius: BorderRadius.circular(radius),
          child: BackdropFilter(
            filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
            child: Container(
              decoration: BoxDecoration(
                color: Colors.white.withOpacity(opacity),
                borderRadius: BorderRadius.all(Radius.circular(radius)),
                border: Border.all(
                  width: 1.5,
                  color: Colors.white.withOpacity(0.2),
                ),
              ),
              child: child,
            ),
          ),
        );
      }
    }

Smileyface.dart

import 'package:flutter/material.dart';

class SmileFaceCheckbox extends StatefulWidget {
  final double height;
  final bool isActive;
  final VoidCallback onPress;
  final Color activeColor;
  final Color deactiveColor;

  const SmileFaceCheckbox({
    Key? key,
    this.height = 24.0,
    required this.isActive,
    required this.onPress,
  })  : activeColor = const Color.fromARGB(255, 116, 217, 48),
        deactiveColor = const Color(0xffD94530),
        super(key: key);

  @override
  State<SmileFaceCheckbox> createState() => _SmileFaceCheckboxState();
}

class _SmileFaceCheckboxState extends State<SmileFaceCheckbox>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animationValue;

  void setupAnimation() {
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 300),
    );

    _animationValue = CurvedAnimation(
      parent: _animationController,
      curve: const Interval(0.0, 1.0),
    );
  }

  @override
  void initState() {
    setupAnimation();
    super.initState();
  }

  @override
  void dispose() {
    _animationController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final height = widget.height;
    final width = height * 2;
    final largeRadius = (height * 0.9) / 2;
    final smallRadius = (height * 0.2) / 2;
    return GestureDetector(
      onTap: widget.onPress,
      child: AnimatedBuilder(
        animation: _animationController,
        builder: (context, _) {
          if (widget.isActive) {
            _animationController.forward();
          } else {
            _animationController.reverse();
          }
          return Container(
            height: height,
            width: width,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(80.0),
              color:
                  widget.isActive ? widget.activeColor : widget.deactiveColor,
             
            ),
            child: Stack(
              alignment: Alignment.center,
              children: [
                Transform.translate(
                  offset: Offset(
                      -largeRadius + largeRadius * 2 * _animationValue.value,
                      0), // add animation move from -largeRadius to largeRadius
                  child: Container(
                    width: largeRadius * 2,
                    height: largeRadius * 2,
                    decoration: const BoxDecoration(
                      color: Colors.white,
                      shape: BoxShape.circle,
                    ),
                    child: Stack(
                      alignment: Alignment.center,
                      children: [
                        Transform.translate(
                          offset: Offset(0, -smallRadius),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.spaceAround,
                            children: [
                              Container(
                                width: smallRadius * 2,
                                height: smallRadius * 2,
                                decoration: BoxDecoration(
                                  color: widget.isActive
                                      ? widget.activeColor
                                      : widget.deactiveColor,
                                  shape: BoxShape.circle,
                                ),
                              ),
                              Container(
                                width: smallRadius * 2,
                                height: smallRadius * 2,
                                decoration: BoxDecoration(
                                  color: widget.isActive
                                      ? widget.activeColor
                                      : widget.deactiveColor,
                                  shape: BoxShape.circle,
                                ),
                              ),
                            ],
                          ),
                        ),
                        Transform.translate(
                          offset: Offset(0, smallRadius * 2),
                          child: Container(
                            width: smallRadius * 4,
                            height:
                                widget.isActive ? smallRadius * 2 : smallRadius,
                            decoration: BoxDecoration(
                              color: widget.isActive
                                  ? widget.activeColor
                                  : widget.deactiveColor,
                              borderRadius: !widget.isActive
                                  ? BorderRadius.circular(22.0)
                                  : const BorderRadius.only(
                                      bottomLeft: Radius.circular(40.0),
                                      bottomRight: Radius.circular(40.0),
                                    ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

How can I resolve the RenderFlex overflowed error in my Flutter app, ensuring all content fits within the available space without overflow?

Any insights or solutions would be greatly appreciated. Thank you!


Solution

  • I think you can use bottomNavigationBar for adding that item. and use Column[HeaderWidget,Expanded(ListViwe)] or just body:ListView on Scaffold body .

    You can play with decoration, It depends on your ux how you like to handle scroll event, you may like SliverAppBar on CustomScrolView

    class _ToDoPageState extends State<ToDoPage> {
      bool isActive = false;
      @override
      Widget build(BuildContext context) {
        return SafeArea(
          child: Scaffold(
            backgroundColor: Color.fromARGB(255, 42, 36, 36),
            // floatingActionButton: newTaskButton(),
            bottomNavigationBar: newTaskButton(),
            body: LayoutBuilder(
              builder: (context, constraints) => Stack(
                children: [
                  SizedBox(
                    height: MediaQuery.of(context).size.height,
                    width: MediaQuery.of(context).size.width,
                    //   child: Image.asset(
                    //     "assets/mountain.jpg",
                    //     fit: BoxFit.cover,
                    //   ),
                  ),
                  SingleChildScrollView(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: [
                        const SizedBox(
                          height: 20.0,
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Expanded(
                              child: Padding(
                                padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                                child: Align(
                                  alignment: Alignment.topLeft,
                                  child: Text(
                                    'My success list',
                                    style: GoogleFonts.nunito(
                                      color: Colors.white,
                                      fontSize: 30.0,
                                      fontWeight: FontWeight.w500,
                                    ),
                                  ),
                                ),
                              ),
                            ),
                            Padding(
                              padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                              child: Tooltip(
                                message: 'List options menu',
                                child: Semantics(
                                  label: 'My success list options menu',
                                  enabled: true,
                                  readOnly: true,
                                  child: IconButton(
                                    icon: const Icon(
                                      Icons.more_vert_outlined,
                                      color: Colors.white,
                                      size: 25,
                                      semanticLabel:
                                          'Pomodoro timer list options menu',
                                    ),
                                    onPressed: () {},
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                        Padding(
                          padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                          child: Align(
                            alignment: Alignment.topLeft,
                            child: Text(
                              'Thusrday, December 29, 2022',
                              style: GoogleFonts.nunito(
                                color: Colors.white,
                                fontSize: 20.0,
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.fromLTRB(23, 8, 23, 8),
                          child: Align(
                            alignment: Alignment.center,
                            child: Glassmorphism(
                              blur: 5,
                              opacity: 0.2,
                              radius: 15,
                              child: Container(
                                height: 100,
                                padding: const EdgeInsets.all(8),
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.stretch,
                                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                                  children: [
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.spaceBetween,
                                      children: [
                                        Text(
                                          'task 1',
                                          style: GoogleFonts.nunito(
                                            color: Colors.white,
                                            fontSize: 24.0,
                                            fontWeight: FontWeight.bold,
                                          ),
                                        ),
                                        SmileFaceCheckbox(
                                            isActive: isActive,
                                            onPress: () {
                                              setState(() {
                                                isActive = !isActive;
                                              });
                                            }),
                                      ],
                                    ),
                                    Align(
                                      alignment: Alignment.topLeft,
                                      child: Text(
                                        'Explain note',
                                        textAlign: TextAlign.center,
                                        style: GoogleFonts.nunito(
                                          color: Colors.white.withOpacity(0.8),
                                          fontSize: 16.0,
                                        ),
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          ),
                        ),
                        //hiint
    
                        // SizedBox(
                        //   height: constraints.maxHeight * .4, // your height
                        // ),
                        // Align(
                        //   alignment: FractionalOffset.bottomCenter,
                        //   child: newTaskButton(),
                        // ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    
      Column newTaskButton() {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.end,
          mainAxisSize: MainAxisSize.min,
          children: [
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
              child: Glassmorphism(
                blur: 20,
                opacity: 0.1,
                radius: 15.0,
                child: TextButton(
                  onPressed: () {
                    // handle push to HomeScreen
                  },
                  child: Container(
                    padding: const EdgeInsets.symmetric(
                      vertical: 10.0,
                      horizontal: 15.0,
                    ),
                    child: Text(
                      '+ Add successful task',
                      style: GoogleFonts.nunito(
                        color: Colors.white,
                        fontSize: 20.0,
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ],
        );
      }
    }