Crie um rodapé fixo com uma exibição de corpo rolável no Flutter

Tempo de leitura: 3 minutes

Crie um widget que contenha um cabeçalho e, mais importante, um rodapé que obviamente deve permanecer no final da tela

Então ?

você dirá Simplesmente usarei o widget EXPANDED sobre meu corpo para que ele ocupe todo o espaço e deixe um pouco na parte superior e inferior do cabeçalho e rodapé Então, o que você está oferecendo!

MAS e se o Body for Scrollable (ex: listview) você sabe com certeza que não pode usar um widget EXPANDEDx sobre um Scrollable Widget.

Se a sua lista sempre tem itens que empurram o rodapé para baixo, então você não tem problema,

mas e se não?

e não se esqueça que sua lista é rolável

para criar um rodapé autoadesivo em vibração, usaremos Slivers,

Uma fatia é uma parte de uma área scrollable que você pode definir para se comportar de uma maneira especial. Você pode usar slivers para obter efeitos scrolling personalizados, como scrolling elástico.

https://flutter.dev/docs/development/ui/advanced/slivers

Bem, vamos começar usando um CustomScroll que funciona com nossos slivers. O primeiro filho será o SliverList que conterá o cabeçalho e o corpo.

Observe que você DEVE usar shrinkWrap:true em sua lista, para que você possa forçar sua lista a ocupar apenas o espaço necessário.

o segundo filho do nosso CustomScroll é o SliverFillRemaining, como o nome indica, vamos colocar o Footer aqui e torná-lo Algin na parte inferior do espaço restante.

observe que o comportamento padrão para o SliverFillRemaining é ter um corpo scroallable para seu filho, não se esqueça de mudar isso.

import 'package:flutter/material.dart';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverList(
            delegate: SliverChildListDelegate(
              [
                Container(
                  width: double.infinity,
                  height: 50,
                  color: Colors.orangeAccent,
                  child: Center(
                    child: Text(
                      'Header',
                      style: TextStyle(color: Colors.white, letterSpacing: 4),
                    ),
                  ),
                ),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                      title: Center(child: Text('$index')),
                    );
                  },
                ),
              ],
            ),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                width: double.infinity,
                height: 50,
                color: Colors.blueAccent,
                child: Center(
                  child: Text(
                    'Footer',
                    style: TextStyle(color: Colors.white, letterSpacing: 4),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}

Você sempre pode substituir este cabeçalho por um widget mais poderoso, SliverAppBar com opções mais sofisticadas, como float, snap, pinned..

ver:

https://api.flutter.dev/flutter/material/SliverAppBar-class.html

import 'package:flutter/material.dart';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
              expandedHeight: 100.0,
              floating: true,
              pinned: false,
              snap: false,
              flexibleSpace: const FlexibleSpaceBar(
                title: Text('Available seats'),
              ),
              actions: <Widget>[
                IconButton(
                  icon: const Icon(Icons.add_circle),
                  tooltip: 'Add new entry',
                  onPressed: () {},
                ),
              ]),
          SliverList(
            delegate: SliverChildListDelegate(
              [
                // Container(
                //   width: double.infinity,
                //   height: 50,
                //   color: Colors.orangeAccent,
                //   child: Center(
                //     child: Text(
                //       'Header',
                //       style: TextStyle(color: Colors.white, letterSpacing: 4),
                //     ),
                //   ),
                // ),
                ListView.builder(
                  shrinkWrap: true,
                  itemCount: 100,
                  itemBuilder: (BuildContext context, int index) {
                    return ListTile(
                      title: Center(child: Text('$index')),
                    );
                  },
                ),
              ],
            ),
          ),
          SliverFillRemaining(
            hasScrollBody: false,
            child: Align(
              alignment: Alignment.bottomCenter,
              child: Container(
                width: double.infinity,
                height: 50,
                color: Colors.blueAccent,
                child: Center(
                  child: Text(
                    'Footer',
                    style: TextStyle(color: Colors.white, letterSpacing: 4),
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    );
  }
}