title: How to implement position: sticky and bottom 0 with Flutter?
body: <p>I want to build a list view with sticky footer like <a href="https://medium.com/@elad/css-position-sticky-how-it-really-works-54cd01dc2d46" rel="nofollow noreferrer">this article</a>'s "Stick to the bottom?!" in Flutter.</p>
  
  <p><a href="https://i.stack.imgur.com/Menrt.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Menrt.png" alt="enter image description here"></a></p>
  
  <p>In CSS,</p>
  
  <pre><code>.main-footer{     
       position: sticky; 
       bottom: 0;
  }
  </code></pre>
  
  <p>but how to do with Flutter?</p>
  
  <h1>What I want</h1>
  
  <ol>
  <li>Scrollable large content</li>
  <li>Footer (sticky)</li>
  <li>Scrollable large content</li>
  </ol>
  
  <p>1 and 2 are visible at First (Scrollable content and fixed footer). After scroll to end of 1, Footer (2) become not fixed. Rest of contents (3) will be shown below footer(2).</p>
  
  <p>I tried to implement above with <a href="https://docs.flutter.io/flutter/widgets/CustomScrollView-class.html" rel="nofollow noreferrer">CustomScrollView</a> but footer button is not drawn above list.</p>
  
  <p><a href="https://i.stack.imgur.com/agxkE.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/agxkE.png" alt="enter image description here"></a></p>
  
  <h2>code</h2>
  
  <pre><code>import 'dart:math';
  import 'package:flutter/material.dart';
  import 'package:flutter/rendering.dart';
  
  void main() =&gt; runApp(MyApp());
  
  class MyApp extends StatelessWidget {
    // This widget is the root of your application.
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        title: 'Fixed footer',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: Scaffold(
          body: _FixedFooterDemo(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {},
            child: Icon(Icons.add),
          ),
        ),
      );
    }
  }
  
  class _FixedFooterDemo extends StatelessWidget {
    const _FixedFooterDemo({
      Key key,
    }) : super(key: key);
  
    @override
    Widget build(BuildContext context) {
      return CustomScrollView(
        slivers: &lt;Widget&gt;[
          SliverAppBar(
            title: Text('Fixed footer'),
          ),
          SliverList(
            delegate: SliverChildListDelegate(List.generate(20, _buildListItem)),
          ),
          SliverStickyFooter(
            child: Center(
              child: RaisedButton(
                onPressed: () {},
                child: Text('Fixed under list button'),
              ),
            ),
          ),
          SliverFillRemaining(
            child: Container(
              color: Colors.yellow,
              child: Center(
                child: Text('below space'),
              ),
            ),
          ),
        ],
      );
    }
  
    ListTile _buildListItem(int i) {
      return ListTile(
        title: Text(
          'Item $i',
        ),
        subtitle: Text(
          'Sit est ipsum consequat sit ex. Minim magna laborum dolore aliqua sit dolore velit sint fugiat. Culpa officia tempor proident minim aliquip nisi reprehenderit ullamco duis mollit. Aute velit irure ut Lorem pariatur anim mollit cillum dolor irure quis. Eu officia dolore deserunt do est cupidatat duis elit. Pariatur magna reprehenderit aliquip ea irure Lorem sunt aute.',
          maxLines: 2,
        ),
      );
    }
  }
  
  class SliverStickyFooter extends SingleChildRenderObjectWidget {
    const SliverStickyFooter({
      Key key,
      Widget child,
    }) : super(key: key, child: child);
  
    @override
    RenderSliverStickyFooter createRenderObject(BuildContext context) =&gt;
        RenderSliverStickyFooter();
  }
  
  class RenderSliverStickyFooter extends RenderSliverSingleBoxAdapter {
    /// Creates a [RenderSliver] that wraps a [RenderBox] which is sized to fit
    /// the remaining space in the viewport.
    RenderSliverStickyFooter({
      RenderBox child,
    }) : super(child: child);
  
    @override
    void performLayout() {
      child?.layout(
        constraints.asBoxConstraints(),
        parentUsesSize: true,
      );
  
      final paintedChildSize =
          calculatePaintOffset(constraints, from: 0.0, to: child.size.height);
      assert(paintedChildSize.isFinite);
      assert(paintedChildSize &gt;= 0.0);
      geometry = SliverGeometry(
        scrollExtent: child.size.height,
        paintExtent: paintedChildSize,
        maxPaintExtent: paintedChildSize,
        hasVisualOverflow: true,
        paintOrigin: -child.size.height + paintedChildSize,
        visible: true,
      );
  
      if (child != null) {
        setChildParentData(child, constraints, geometry);
      }
    }
  }
  </code></pre>