Search code examples
flutterdartflutter-layout

Stack() Widget not centering all sub widgets flutter


I have a Text() widget I am trying to stack on a CircularProgressIndicator()

I thought it would be as simple as just wrapping them both in a Stack() widget but the text is not centered.

I tried wrapping the Text() in a Center() widget but that did not solve the issue:

                    return Expanded(
                      child: PageView(
                        controller: pageViewController,
                        children: [
                          PackSummaryWeightGraph(
                              categoryWeightList: categoryWeightList,
                              totalWeight: totalWeight),
                          Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                              Center(
                                child: Stack(
                                  children: [
                                    Text((packedItemsPercent * 100)
                                        .toString()),
                                    SizedBox(
                                      height: 150,
                                      width: 150,
                                      child: CircularProgressIndicator(
                                        value: packedItemsPercent,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ],
                          ),
                          const Center(
                            child: Text('Third Page'),
                          ),
                        ],
                      ),
                    );

Bonus points if there is a way to have the CircularProgressIndicator() fill the space without hard coding its width and height...

enter image description here


Solution

  • Stack has an alignment argument:

    Stack(
      alignment: Alignment.center, 
      children: [...],
    ),
    

    If you want to fill the given space use the SizedBox.expand constructor:

    SizedBox.expand(
      child: CircularProgressIndicator(
        value: packedItemsPercent,
      ),
    ),
    

    One issue with the above is that if the available space has a different height than width you will end up with an oval shaped indicator rather than a circle. You can avoid this by wrapping it in an AspectRatio widget:

    AspectRatio(
      aspectRatio: 1,
      child: SizedBox.expand(
        child: CircularProgressIndicator(
          value: packedItemsPercent,
        ),
      ),
    ),
    

    See complete demo:

    import 'package:flutter/material.dart';
    
    void main() {
      double packedItemsPercent = .67;
    
      runApp(
        MaterialApp(
          home: Scaffold(
            body: Stack(
              alignment: Alignment.center,
              children: [
                Text((packedItemsPercent * 100).toString()),
                AspectRatio(
                  aspectRatio: 1,
                  child: SizedBox.expand(
                    child: CircularProgressIndicator(
                      value: packedItemsPercent,
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      );
    }
    

    Make sure that any widget like Expanded or SizedBox.expand is not inside of an infinite sized container like a ListView or similar. Expanded means to take up the maximum available space, but that isn't possible if you have an infinite amount of space.