Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a scroll view with fixed footer with Flutter?

I would like to create a view that has to have a Column with a scroll view (e.g. something like SingleChildScrollView) and a footer regardless of the screen size. If the screen is big enough, it will use the empty space between the scroll and the footer, if not, it will expand and only make the widget above the footer scrollable.

It's more or less like Listview with scrolling Footer at the bottom but with a diference that I want the keyboard to overflow the footer and it also should stay in place.

Something like

example

return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          SingleChildScrollView(
            child: Padding(
              padding: const EdgeInsets.only(left: 30.0, right: 30.0, top: 80.0),
              child: Form(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: <Widget>[
                   // Multiple widgets and form fields
                  ],
                ),
              ),
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 50.0),
            child: SafeArea(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  // Footer widgets
                ],
              ),
            ),
          )
        ],
      ),
    );
like image 520
Miguel Ruivo Avatar asked Jan 03 '19 17:01

Miguel Ruivo


People also ask

How do you add a footer to a ListView in flutter?

First,during building the list view just add +1 with itemCount property of ListView. Builder. And during returning the Widget just use check the index of ListView if it is equal to the Length of the passed List in ListView. Builder simply return SizedBox with required height of Footer, and thats it.

How do I create a footer in flutter?

FooterView Class The flutter footer uses a component called FooterView. The FooterView Component takes 3 arguments which are as follows: children : this is a Scrollable List of Widgets. footer : Takes a Footer Component that takes a Customizable Widget e.g a Container Widget.


2 Answers

For those who were looking to implement just footer with scrollview in a simple way, below code might help :

Scaffold(
      appBar: buildAppBar('Some cool appbar'),
      body: Column(
        children: [
          Expanded(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  PackageCard(),
                  PackageCard(),
                  PackageCard(),
                ],
              ),
            ),
          ),
          Container(
            child: Text('Your super cool Footer'),
            color: Colors.amber,
          )
        ],
      ),
    );

Visual representation:-

---Column
    |
    |---Expanded--
                 |-SingleChildScrollView (column /YOUR SCROLLABLE VIEW)
    |
    |-Container(YOUR FOOTER)

I used expanded with SinglechildScrollView over here

like image 155
abhay tripathi Avatar answered Sep 28 '22 15:09

abhay tripathi


The difficulty is that Column and SingleChildScrollView have a hard time working together because one needs constraints and the other removes them.

The trick is to use a CustomMultiChildLayout and do the calculations yourself. Helped by MediaQuery to obtain the size of the keyboard, so that the footer can disappear to leave more room for the content.

Here's a reusable widget that does it for you:

class FooterLayout extends StatelessWidget {
  const FooterLayout({
    Key key,
    @required this.body,
    @required this.footer,
  }) : super(key: key);

  final Container body;
  final Container footer;

  @override
  Widget build(BuildContext context) {
    return CustomMultiChildLayout(
      delegate: _FooterLayoutDelegate(MediaQuery.of(context).viewInsets),
      children: <Widget>[
        LayoutId(
          id: _FooterLayout.body,
          child: body,
        ),
        LayoutId(
          id: _FooterLayout.footer,
          child: footer,
        ),
      ],
    );
  }
}

enum _FooterLayout {
  footer,
  body,
}

class _FooterLayoutDelegate extends MultiChildLayoutDelegate {
  final EdgeInsets viewInsets;

  _FooterLayoutDelegate(this.viewInsets);

  @override
  void performLayout(Size size) {
    size = Size(size.width, size.height + viewInsets.bottom);
    final footer =
        layoutChild(_FooterLayout.footer, BoxConstraints.loose(size));

    final bodyConstraints = BoxConstraints.tightFor(
      height: size.height - max(footer.height, viewInsets.bottom),
      width: size.width,
    );

    final body = layoutChild(_FooterLayout.body, bodyConstraints);

    positionChild(_FooterLayout.body, Offset.zero);
    positionChild(_FooterLayout.footer, Offset(0, body.height));
  }

  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}

Used as such:

FooterLayout(
  body: body,
  footer: footer,
),
like image 36
Rémi Rousselet Avatar answered Sep 28 '22 15:09

Rémi Rousselet