Flutter Web and Slivers
Tags: flutter, dart, webdev, productivity
Published: 2020-08-01 05:40:16

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>


<!-- wp:heading {"level":3} -->
<h3>Begin…</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>View the demo here</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p><strong><em>Website: </em></strong><a rel="noreferrer noopener" href="https://fir-signin-4477d.firebaseapp.com/#/" target="_blank"><strong><em>https://fir-signin-4477d.firebaseapp.com/#/</em></strong></a></p>
<!-- /wp:paragraph -->

{% youtube 9HeDrna9TII %}

####Article here: https://flatteredwithflutter.com/flutter-web-and-slivers/

<!-- wp:paragraph -->
<p>We will cover briefly about</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li><strong>Slivers</strong></li></ol>
<!-- /wp:list -->

<!-- wp:heading {"level":4} -->
<h4>What are&nbsp;Slivers?</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>As per the official doc:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A sliver is a portion of a scrollable area. You can use slivers to achieve custom scrolling effects.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>You have possibly the entire control for implementing a scrollable area while using them. Because slivers can lazily build, they are particularly useful for scrolling through a large number of children.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>One of the best articles on Slivers, <a href="https://medium.com/flutter/slivers-demystified-6ff68ab0296f" target="_blank" rel="noreferrer noopener">here</a>.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:heading {"level":4} -->
<h4>How to use Slivers in Flutter Web?</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Just as you use, let's say, <a rel="noreferrer noopener" href="https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html" target="_blank"><strong>SingleChildScrollView</strong></a> for implementing a normal scrolling behavior, in terms of Slivers, you simply wrap your children inside a <a rel="noreferrer noopener" href="https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html" target="_blank"><strong>CustomScrollView</strong></a></p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>CustomScrollView(
  slivers: &lt;Widget>&#91;
    const SliverAppBar(
      pinned: true,
      expandedHeight: 250.0,
      flexibleSpace: FlexibleSpaceBar(
        title: Text('Demo'),
      ),
    ),
    SliverFixedExtentList(
      itemExtent: 50.0,
      delegate: SliverChildBuilderDelegate(
        (BuildContext context, int index) {
          return Container(
            alignment: Alignment.center,
            color: Colors.lightBlue&#91;100 * (index % 9)],
            child: Text('List Item $index'),
          );
        },
      ),
    ),
  ],
)</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Without slivers, you would have something like this</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SingleChildScrollView(<br>   child: Column(<br>      mainAxisSize: MainAxisSize.min,<br>      children: &lt;Widget&gt;[<br>         // WIDGETS           <br>      ]           <br>   )            <br>);</pre>
<!-- /wp:preformatted -->

<!-- wp:heading {"level":4} -->
<h4>Sliver Widgets used for the&nbsp;demo</h4>
<!-- /wp:heading -->

<!-- wp:list {"ordered":true} -->
<ol><li><strong>SliverList</strong></li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>As per the docs:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A sliver that places multiple box children in a linear array along the main axis.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*kptP7bNrswgBQGTpneyr0g.png" alt="Flutter Web and Slivers"/><figcaption>Flutter Web and Slivers</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>SliverList takes a delegate parameter. </p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverList(<br>   delegate: // 2 OPTIONS,<br>),</pre>
<!-- /wp:preformatted -->

<!-- wp:list -->
<ul><li>Option1 (<strong>SliverChildListDelegate): </strong>You can specify the predefined list of children with this.</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverList(<br>    delegate: SliverChildListDelegate(<br>      [<br>        Container(color: Colors.red, height: 150.0),<br>        Container(color: Colors.purple, height: 150.0),<br>        Container(color: Colors.green, height: 150.0),<br>      ],<br>    ),<br>);</pre>
<!-- /wp:preformatted -->

<!-- wp:list -->
<ul><li>Option2 (<strong>SliverChildBuilderDelegate</strong>): Specify the children with this, and they will be built lazily.</li></ul>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverList(<br>    delegate: SliverChildBuilderDelegate((context, int index) {<br>      return Container(color: Colors.blue, height: 150.0);<br>    },<br>    childCount: 10,<br>  ),<br>);</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p><strong>2. SliverPersistentHeader</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per the docs:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>A sliver whose size varies when the sliver is scrolled to the edge of the viewport.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*1E9eT01pm5z5y5gaDXrC9Q.png" alt="Flutter Web and Slivers"/><figcaption>Flutter Web and Slivers</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>Here, the 2nd Widget (Disappear-header Sliver) is a <strong>SliverPersistentHeader.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As you scroll down, this widget sticks to the top of the page.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"width":580,"height":370} -->
<figure class="wp-block-image is-resized"><img src="https://cdn-images-1.medium.com/max/1600/1*7BJg7lZi4SvkIGSJpChvRA.png" alt="Flutter Web and Slivers" width="580" height="370"/><figcaption>Flutter Web and Slivers</figcaption></figure>
<!-- /wp:image -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverPersistentHeader(<br>   pinned: true,<br>   floating: true,<br>   delegate: _SliverDelegate(child: _menu),<br>),</pre>
<!-- /wp:preformatted -->

<!-- wp:list -->
<ul><li><strong>pinned</strong>: Whether to stick the header to the start of the viewport once it has reached its minimum size.</li><li><strong>floating</strong>: Whether the header should immediately grow again if the user reverses the scroll direction.</li><li>delegate parameter of the type <strong>SliverPersistentHeaderDelegate</strong>.</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>class _SliverDelegate implements SliverPersistentHeaderDelegate {
  _SliverDelegate({
    this.minHeight = 40.0,
    this.maxHeight = 56.0,
    @required this.child,
  });
final double minHeight;
  final double maxHeight;
  final Widget child;
@override
  Widget build(
    BuildContext context,
    double shrinkOffset,
    bool overlapsContent,
  ) {
    return SizedBox.expand(child: child);
  }
@override
  double get maxExtent => math.max(maxHeight, minHeight);
@override
  double get minExtent => minHeight;
@override
  bool shouldRebuild(_SliverDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
@override
  FloatingHeaderSnapConfiguration get snapConfiguration => null;
@override
  OverScrollHeaderStretchConfiguration get stretchConfiguration => null;
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>3. <strong>SliverAppBar</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per the docs&nbsp;:</p>
<!-- /wp:paragraph -->

A material design app bar that integrates with a CustomScrollView.

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*SzcxZoPsYAL5NflNmivARg.png" alt="Flutter Web and Slivers"/><figcaption>Flutter Web and Slivers</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>As you scroll up, the app bar disappears, and you see the list of colors only. Something just like this:</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","width":236,"height":480} -->
<div class="wp-block-image"><figure class="aligncenter is-resized"><img src="https://cdn-images-1.medium.com/max/1600/0*qD50sOHGBo-49kFU.gif" alt="SliverAppBar" width="236" height="480"/><figcaption>SliverAppBar</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Good interactive demos <a href="https://api.flutter.dev/flutter/material/SliverAppBar-class.html" rel="noreferrer noopener" target="_blank">here</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverAppBar(
  automaticallyImplyLeading: false,
  title: titleWidget,
  backgroundColor: AppColors.brandColor,
  expandedHeight: expandedHeight,
  flexibleSpace: FlexibleSpaceBar(
     background: Image.asset(image.assetName),
  ), 
),</pre>
<!-- /wp:preformatted -->

<!-- wp:heading {"level":4} -->
<h4>Properties</h4>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li><strong>automaticallyImplyLeading</strong>: To show the back arrow or not.</li><li><strong>title</strong>: What widget to show (e.g here Text(‘SliverAppbar’))</li><li><strong>expandedHeight</strong>: Size of the app bar when it is fully expanded.</li><li><strong>flexibleSpace</strong>: Stacked behind the toolbar and the tab bar. The image in our case</li><li><strong>floating</strong>: (By default, false) Whether the app bar should become visible as soon as the user scrolls towards the app bar.</li><li><strong>pinned</strong>: (By default, false) Whether the app bar should remain visible at the start of the scroll view.</li></ul>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: For the demo, the default properties were good enough for me&nbsp;:)</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>4. <strong>SliverToBoxAdapter</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>As per the docs:</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Creates a sliver that contains a single box widget.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">SliverToBoxAdapter(<br>   child: Container(<br>     color: const Color(0xFF9b9987),<br>     height: 300.0,<br>     child: Center(<br>       child: Text('SliverToBoxAdapter'),<br>     ),<br>   ),<br>)</pre>
<!-- /wp:preformatted -->

Think of it as an alternative to a SizedBox, but for the sliver widgets.

<!-- wp:image -->
<figure class="wp-block-image"><img src="https://cdn-images-1.medium.com/max/1600/1*7gC7UEqWKxg_HNEcYbuJrQ.png" alt="SliverToBoxAdapter"/><figcaption>SliverToBoxAdapter</figcaption></figure>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>5: <strong>SliverPadding</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>This is basically, “The amount of space by which to inset the child sliver.”</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the above screenshot, the white gap which you see between two widgets is the result of the <strong>SliverPadding</strong>.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>SliverPadding(
    padding: const EdgeInsets.symmetric(vertical: 24.0),
    sliver: SliverFillRemaining(
      child: Container(
        color: const Color(0xFF442220),
        child: Center(
           child: Text(
             'SliverFillRemaining',
             style: TextStyle(color: Colors.white),
           ),
        ),
      ),
    ),
)</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>6: <strong>SliverFillRemaining</strong></p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>A sliver that contains a single box child that fills the remaining space. This should be the last sliver, as there is never any room for anything beyond this.</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>In the above example, the SliverFillRemaining covers the available space.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><strong>Production Tips :</strong></p></blockquote>
<!-- /wp:quote -->

<!-- wp:list -->
<ul><li>In case you have a list of children, consider using <strong>SliverList, </strong>as they efficiently render the children.</li><li>For efficiently rendering a list inside Slivers, use <strong>SliverChildBuilderDelegate.</strong></li><li>In order to have a customizable SliverAppBar, use <strong>SliverPersistentHeader, </strong>since SliverAppbar uses this under the hood.</li><li>For showing grids inside Slivers, consider using <a rel="noreferrer noopener" href="https://medium.com/flutter/slivers-demystified-6ff68ab0296f" target="_blank"><strong>SliverGrid</strong></a><strong>.</strong></li><li>If each of the child height is fixed, you may switch to <strong>SliverFixedExtentList</strong></li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>SliverFixedExtentList(
  itemExtent: 50.0,
  delegate: SliverChildBuilderDelegate(
    (BuildContext context, int index) {
      return Container(
        alignment: Alignment.center,
        color: Colors.lightBlue&#91;100 * (index % 9)],
        child: Text('list item $index'),
      );
    },
  ),
)</code></pre>
<!-- /wp:code -->

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Codepen: <a href="https://codepen.io/aseemwangoo/pens/" rel="noreferrer noopener" target="_blank">https://codepen.io/aseemwangoo/pens/</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Hosted URL&nbsp;: <a href="https://fir-signin-4477d.firebaseapp.com/#/" rel="noreferrer noopener" target="_blank">https://fir-signin-4477d.firebaseapp.com/#/</a></p></blockquote>
<!-- /wp:quote -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p><a href="https://github.com/AseemWangoo/experiments_with_web" rel="noreferrer noopener" target="_blank">Source code for Flutter Web App..</a></p></blockquote>
<!-- /wp:quote -->

{% youtube 9HeDrna9TII %}