TLDR: I can't wrap my head around how SingleChildScrollView works in daily-use contexts, such a centered well formatted Log-In form.
Premise: I even made the mistake of adding a new Flutter issue about this (I initally thought the documentation was "wrong").
Previous search: my search included the following questions/answers, but I am not yet satisfied:
- SingleChildScrollView + Column: either overflow or ignore mainAxisAlignment;
- MainAxisAlignment under SingleChildScrollView is not working;
- The Documentation about this is not sufficient (at least for me / my problem, but maybe I just don't understand it).
Problem: I stumbled upon the following inconsistency: say you have to code a simple Log-In form. My log-in form is composed of some Images and an Expanded widget whose child is a Form.
I want such form to have several fields, so I'm using another Column with MainAxisAlignment.center inside it, which works perfectly fine, i.e. as intended: everything is centered, "good looking".
Now, I want such Column to be scrollable, for obvious reasons, and here's where the inconsistencies occur.
Whenever such Column is wrapped inside a SingleChildScrollView, the Column widget is shrinked down to the bare minimum. The Expanded option is not ignored (that's good), but instead the _SingleChildViewport is the Widget actually expanding on the UI (that's bad: I expect the actual column to expand).
Therefore, the MainAxisAlignment.center is now useless, since now all the content is "compressed" up to the top; I tried a workaround with the MainAxisSize.max option on the column, but it is simply left ignored.
I found some clever workarounds (this comment), but it really doesn't feel right / consistent to code like that, or at least it doesn't explain why it behaves like this.
Example Code
This should suffice as an example.
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(height: 50), // some other widgets, decorations, etc.
Expanded( // the Form i need
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center, // USELESS
mainAxisSize: MainAxisSize.max, // IGNORED
children: [
const Text("Some label"),
TextField(...),
const SizedBox(height: 5),
const Text("Some other label"),
TextField(...),
ElevatedButton(
onPressed: doStuff(),
child: const Text(
"......",
),
),
],
),
),
),
const SizedBox(height: 50), // some more decorations...
],
)
Expected results: A evenly-distributed form
Actual results: A compressed-to-the-top form.
Workaround Code
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 50),
Expanded(
child: Center( // WORKAROUND
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Some label"),
TextField(...),
const SizedBox(height: 5),
const Text("Some other label"),
TextField(...),
ElevatedButton(
onPressed: doStuff(),
child: const Text(
"......",
),
),
],
),
),
),
),
const SizedBox(height: 50),
],
);
While using the Flutter DevTools, you can see that in the workaround solution the view port of the SingleChildScrollView (_SingleChildViewport) disappears, as it is "incorporated" in the Center widget. I can't really understand why or how this should work.
My question, in the end, is: why does it behave like this? Why does the viewport widget take off the remaining space of the column (I'd expect the column widget to expand, instead, since that's what I've written in my code...).