Search code examples
flutteruser-interface

Flutter column with header and footer elements of same height and expanded middle element


In flutter I have a GoBackPage that I use to surround some subscreens with. It's basically a Column[Icon,Expanded(child: child)]

    class GoBackPage extends StatelessWidget {
      late Widget? child;
      bool deadSpace;
    
      GoBackPage({
        super.key,
        this.child,
        this.deadSpace = true,
      });
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Padding(
              padding: EdgeInsets.all(8.0),
              child: Card(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Column(
                    children: [
                      Align(
                        alignment: Alignment.topLeft,
                        child: IconClickable(
                          iconData: Icons.arrow_back,
                          color: MyThemeProvider.primary,
                          size: 32.0,
                          onTap: () {
                            context.pop();
                          },
                        ),
                      ),
                      if (child != null) ...[
                        Expanded(
                          child: child!,
                        ),
                      ],
                      // How to leave as much space as the first element?
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      }
    }

The only problem I have is that the child, for example a Column with MainAxisAlignment.center, or a button surrounded by a Center, will feel vertically misaligned downwards because the icon took some vertical space. I would like to leave as much empty space under the child as the first item (the icon) took.

In other words, is it possible to have a distribution like this in a column?

    ///////////
    //
    // 1. TAKE WHAT I NEED (UNKNOWN AT COMPILATION TIME)
    //
    ///////////
    ///////////
    //
    //
    //
    // 3. CHILD: TAKE ALL THE REST OF SPACE
    //
    //
    //
    ///////////
    ///////////
    //
    // 2. TAKE THE SAME AS THE FIRST ONE TOOK
    //
    ///////////


Solution

  • Expanded fills all available space. This is it's intended purpose. Because of this, if you have more empty space on the bottom than the top, the Expanded will fill that space and look off-center. Two ideas for you:

    Add a SizedBox with height 32 under the Expanded widget:

    Column(
                    children: [
                      Align(
                        alignment: Alignment.topLeft,
                        child: IconClickable(
                          iconData: Icons.arrow_back,
                          color: MyThemeProvider.primary,
                          size: 32.0,
                          onTap: () {
                            context.pop();
                          },
                        ),
                      ),
                      if (child != null) ...[
                        Expanded(
                          child: child!,
                        ),
                      ],
                      SizedBox(height: 32),
                    ],
                  ),
    

    You could also add a bottom padding of 32px.

    Expanded(
      child: Padding(
        padding: const EdgeInsets.only(bottom: 32),
        child: child,
      ),
    ),
    

    To center it perfectly while using the Expanded you have to offset the 32px that the icon is taking up.