Как сделать столбец выровненным по низу внутри прокрутки стека, когда места недостаточно? - PullRequest
0 голосов
/ 11 июля 2020

Overflow error

I am trying to create a modal form. The modal content should stay at the bottom, and can reach max height of windowHeight - top safe area - 56px depending on available space. If there is no more space, it should scroll the body area, that is the form fields and submit button.

Corresponding code:

Stack(
          children: <Widget>[
            InkWell(
              onTap: () => navigator.pop()
            ),
            Align(
              alignment: Alignment.bottomCenter,
              child: IntrinsicHeight(
                child: Container(
                  decoration: BoxDecoration(...radius, background...),
                  child: SafeArea(
                    top: false,
                    child: Column(
                      children: <Widget>[
                        Row(
                          children: <Widget>[
                            // Title & close button
                          ],
                          crossAxisAlignment: CrossAxisAlignment.start,
                        ),
                        Container(
                          padding: EdgeInsets.fromLTRB(...),
                          child: SingleChildScrollView(
                            child: Center(
                              child: Column(
                                children: <Widget>[
                                  CoreTextField(...),
                                  CoreTextField(...),
                                  CoreTextField(...),
                                  CoreTextField(...),
                                  CoreTextField(...),
                                  CoreTextField(...),
                                  CoreButton(...)
                                ],
                              ),
                            ),
                          ),
                        )
                      ],
                    ),
                  ),
                ),
              ),
            )
          ],
        )

Ответы [ 3 ]

0 голосов
/ 11 июля 2020

Вы можете использовать ListView или SingleChildScrolView

0 голосов
/ 11 июля 2020

Оказывается, мне пришлось использовать Column и поместить Align внутри Expanded.

Stack(
   children: <Widget>[
     InkWell(
        onTap: navigator.pop,
     ),
     Align(
        alignment: Alignment.bottomCenter,
        child: Column( // This is an additional wrapper to hold the minimum top spacing and the modal content
          children: <Widget>[
            SizedBox( // Provides minimum spacing at the top on smaller viewports
                height: 56 + MediaQuery.of(context).padding.top,
            ),
            Expanded( // Occupies rest of the screen and provides constraints
              child: Align(
                alignment: Alignment.bottomCenter, // Now that we have constraints, we can push the children down using align
                child: Container(
                  decoration: BoxDecoration(... color & radius ...),
                  child: Column(
                    mainAxisSize: MainAxisSize.min, // Required. Shrinks the contents to minimum possible height.
                    children: <Widget>[
                      Row(... title & close button ...),
                      Flexible( // Not expanded, but flexible. Unlike Expanded, it doesn't force child to take up entire space. This is needed for SingleChildScrollView to work
                        child: SingleChildScrollView( // Makes the form fields scrollable
                          child: Container(
                            padding: EdgeInsets.fromLTRB(SPACING_UNIT * 5, 0, SPACING_UNIT * 5, SPACING_UNIT * 5),
                            child: Column(
                              children: <Widget>[
                                CoreTextField(),
                                CoreTextField(),
                                CoreTextField(),
                                CoreTextField(),
                                CoreTextField(),
                                CoreTextField(),
                                SafeArea(
                                  top: false,
                                  child: CoreButton(),
                                )
                              ],
                            ),
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              ),
            )
          ],
        )
    )
)
0 голосов
/ 11 июля 2020
Stack(
  children: <Widget>[
    InkWell(
      onTap: () => navigator.pop()
    ),
    Align(
      alignment: Alignment.bottomCenter,
      child: IntrinsicHeight(
        child: Container(
          constraints: BoxConstraints(
            maxHeight: MediaQuery.of(context).size.height - 56.0
          ), //maxHeight of the window - 56.0
          decoration: BoxDecoration(...radius, background...),
          child: SafeArea(
            top: false,
            child: Column(
              children: <Widget>[
                Row(
                  children: <Widget>[
                    // Title & close button
                  ],
                  crossAxisAlignment: CrossAxisAlignment.start,
                ),
                Expanded( //Use Expanded instead of Container
                  child: SingleChildScrollView(
                    padding: EdgeInsets.fromLTRB(...),
                    child: Center(
                     child: Column(
                      children: <Widget>[
                        CoreTextField(...),
                        CoreTextField(...),
                        CoreTextField(...),
                        CoreTextField(...),
                        CoreTextField(...),
                        CoreTextField(...),
                        CoreButton(...)
                      ],
                    ),
                  ),
                ))
              ],
            ),
          ),
        ),
      ),
    )
  ],
)

Используйте Expanded вместо Container, Expanded попытается использовать все доступное пространство, а затем SingleChildScrollView будет прокручиваться в этом пространстве, если столбец не поместился

ОБНОВЛЕНИЕ

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    double height = MediaQuery.of(context).size.height;
    double statusBar = MediaQuery.of(context).viewPadding.top;
    double maxSize = (height -56.0 - statusBar)/height;
    return Stack(
      fit: StackFit.loose,
      children: <Widget>[
        InkWell(
          onTap: () => null, //navigator.pop()
        ),
        DraggableScrollableSheet(
          maxChildSize: maxSize, 
          minChildSize: 0.3,// whatever value you want for the minimum, less than max
          initialChildSize: maxSize, 
          //or if you don't want it fully expanded just give it a fraction of maxSize
          //it has to be between maxChildSize and minChildSize
          builder: (context, scrollController){
             return Container(
              decoration: BoxDecoration(...radius, background...),
              child: Column(
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Row(
                      children: <Widget>[
                        // Title & close button
                      ],
                      crossAxisAlignment: CrossAxisAlignment.start,
                    ),
                    Expanded(
                        child: SingleChildScrollView(
                          controller: scrollController,
                      padding: EdgeInsets.fromLTRB(...),
                      child: Center(
                        child: Column(
                          children: <Widget>[
                            CoreTextField(...),
                            CoreTextField(...),
                            CoreTextField(...),
                            CoreTextField(...),
                            CoreTextField(...),
                            CoreTextField(...),
                            CoreButton(...)
                          ],
                        ),
                      ),
                    ))
                  ],
                ),
            );
          },
        )
      ],
    );
  }
}
...