Free AI web copilot to create summaries, insights and extended knowledge, download it at here
7840
Abstract
/span>(
<span class="hljs-attribute">gridDelegate</span>: <span class="hljs-built_in">SliverGridDelegateWithFixedCrossAxisCount</span>(
<span class="hljs-attribute">crossAxisCount</span>: <span class="hljs-number">4</span>,
),
<span class="hljs-attribute">delegate</span>: <span class="hljs-built_in">SliverChildBuilderDelegate</span>(
(BuildContext context, int index) {
return new <span class="hljs-built_in">Container</span>(
<span class="hljs-attribute">color</span>: <span class="hljs-built_in">randomColor</span>(),
<span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>);
}
);</pre></div><figure id="3bd7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*uKP16BI3_8_a9Fk_Q2oNvA.png"><figcaption></figcaption></figure><figure id="0d67"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*WM9-Gu6XUz4CYCS2hXfqSA.png"><figcaption>Visual result of SliverGrid.count and SliverGrid.extent, respectively, from the above code snippets.</figcaption></figure><h1 id="f3c3">SliverAppBar</h1><p id="5846">Okay, okay, enough exposition. Here’s what I know you all have been waiting for. How do I make those gorgeous expanding and contracting app-bars? The secret is to set both the flexibleSpace parameter and the expandedHeight parameter. You can set both for a different height and appearance for your app bar when it is expanded to its full size vs the “compressed” version.</p><figure id="2b42"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*Oz9-FVqgyjDr_wnrbSQEGQ.gif"><figcaption></figcaption></figure><p id="b83f">Here’s the code for the above example:</p><div id="0bdd"><pre><span class="hljs-selector-tag">CustomScrollView</span>(
<span class="hljs-attribute">slivers</span>: <Widget>[
<span class="hljs-built_in">SliverAppBar</span>(
<span class="hljs-attribute">title</span>: <span class="hljs-built_in">Text</span>(<span class="hljs-string">'SliverAppBar'</span>),
<span class="hljs-attribute">backgroundColor</span>: Colors.green,
<span class="hljs-attribute">expandedHeight</span>: <span class="hljs-number">200.0</span>,
<span class="hljs-attribute">flexibleSpace</span>: <span class="hljs-built_in">FlexibleSpaceBar</span>(
<span class="hljs-attribute">background</span>: Image.<span class="hljs-built_in">asset</span>(<span class="hljs-string">'assets/forest.jpg'</span>, <span class="hljs-attribute">fit</span>: BoxFit.cover),
),
),
<span class="hljs-built_in">SliverFixedExtentList</span>(
<span class="hljs-attribute">itemExtent</span>: <span class="hljs-number">150.0</span>,
<span class="hljs-attribute">delegate</span>: <span class="hljs-built_in">SliverChildListDelegate</span>(
[
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.red),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.purple),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.green),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.orange),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.yellow),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.pink),
],
),
),
],
);</pre></div><p id="8ffd">There’s some additional customization you can add on SliverAppBar. You can set the floating parameter to true to make the app bar reappear when you scroll down, even if you haven’t reached the top of the list.</p><figure id="69a4"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*s9aYJJApIUVblNZxOWs8DQ.gif"><figcaption></figcaption></figure><p id="b66b">If you add both the snap parameter with the floating parameter, you can make the app bar fully snap back into view when you scroll down.</p><figure id="e1b7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*vkO1sczH3DPBGPlr3epW_Q.gif"><figcaption></figcaption></figure><h1 id="bde5">Putting it all together: a collapsible scrolling list with SliverPersistentHeader</h1><p id="9d98">I tried to imagine the most unusual scrolling behavior I could think of that still might be useful. I came up with this scrolling collapsible list:</p><figure id="7a2c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*g5kTqAzL6FTJKnFictwJ5w.gif"><figcaption></figcaption></figure><div id="d414"><pre><span class="hljs-keyword">import</span> <span class="hljs-string">'package:flutter/material.dart'</span>;</pre></div><div id="a940"><pre><span class="hljs-keyword">import</span> <span class="hljs-string">'dart:math'</span> <span class="hljs-keyword">as</span> math;</pre></div><div id="2c08"><pre><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">main</span>()</span> => runApp(MyApp());</pre></div><div id="6636"><pre><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyApp</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
<span class="hljs-meta">@override</span>
<span class="hljs-type">Widget</span> build(<span class="hljs-type">BuildContext</span> context) {
<span class="hljs-keyword">return</span> <span class="hljs-type">MaterialApp</span>(
home: <span class="hljs-type">Scaffold</span>(
appBar: <span class="hljs-type">AppBar</span>(title: <span class="hljs-type">Text</span>('<span class="hljs-type">Collapsing</span> <span class="hljs-type">List</span> <span class="hljs-type">Demo</span>')),
body: <span class="hljs-type">CollapsingList</span>(),
),
);
}
}</pre></div><div id="62d1"><pre><span class="hljs-selector-tag">class</span> <span class="hljs-selector-tag">_SliverAppBarDelegate</span> <span class="hljs-selector-tag">extends</span> <span class="hljs-selector-tag">SliverPersistentHeaderDelegate</span> {
<span class="hljs-selector-tag">_SliverAppBarDelegate</span>({
<span class="hljs-variable">@required</span> this.minHeight,
<span class="hljs-variable">@required</span> this.maxHeight,
<span class="hljs-variable">@required</span> this.child,
});</pre></div><div id="a724"><pre> <span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> minHeight;
<span class="hljs-keyword">final</span> <span class="hljs-built_in">double</span> maxHeight;
<span class="hljs-keyword">final</span> Widget child;</pre></div><div id="0314"><pre> <span class="hljs-meta">@override</span>
<span class="hljs-built_in">double</span> <span class="hljs-keyword">get</span> minExtent => minHeight;</pre></div><div id="16eb"><pre> <span class="hljs-meta">@override</span>
<span class="hljs-built_in">double</span> <span class="hljs-keyword">get</span> maxExtent => math.max(maxHeight, minHeight);</pre></div><div id="4940"><pre> @<span class="hljs-function"><span class="hljs-keyword">override</span>
Widget <span class="hljs-title">build</span><span class="hljs-params">(
BuildContext context,
<span class="hljs-type">double</span> shrinkOffset,
<span class="hljs-type">bool</span> overlapsContent)</span>
</span>{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SizedBox.<span class="hljs-built_in">expand</span>(child: child);
}</pre></div><div id="2203"><pre> @<span class="hljs-function"><span class="hljs-keyword">override</span>
<span class="hljs-type">bool</span> <span class="hljs-title">shouldRebuild</span><span class="hljs-params">(_SliverAppBarDelegate old
Options
Delegate)</span> </span>{
<span class="hljs-keyword">return</span> maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}</pre></div><div id="b858"><pre><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CollapsingList</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">StatelessWidget</span> </span>{
<span class="hljs-type">SliverPersistentHeader</span> makeHeader(<span class="hljs-type">String</span> headerText) {
<span class="hljs-keyword">return</span> <span class="hljs-type">SliverPersistentHeader</span>(
pinned: <span class="hljs-literal">true</span>,
delegate: _SliverAppBarDelegate(
minHeight: <span class="hljs-number">60.0</span>,
maxHeight: <span class="hljs-number">200.0</span>,
child: <span class="hljs-type">Container</span>(
color: <span class="hljs-type">Colors</span>.lightBlue, child: <span class="hljs-type">Center</span>(child:
<span class="hljs-type">Text</span>(headerText))),
),
);
}</pre></div><div id="e6e0"><pre> <span class="hljs-variable">@override</span>
Widget <span class="hljs-built_in">build</span>(BuildContext context) {
<span class="hljs-selector-tag">return</span> <span class="hljs-selector-tag">CustomScrollView</span>(
<span class="hljs-attribute">slivers</span>: <Widget>[
<span class="hljs-built_in">makeHeader</span>(<span class="hljs-string">'Header Section 1'</span>),
SliverGrid.<span class="hljs-built_in">count</span>(
<span class="hljs-attribute">crossAxisCount</span>: <span class="hljs-number">3</span>,
<span class="hljs-attribute">children</span>: [
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.red, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.purple, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.green, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.orange, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.yellow, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.pink, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.cyan, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.indigo, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.blue, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
],
),
<span class="hljs-built_in">makeHeader</span>(<span class="hljs-string">'Header Section 2'</span>),
<span class="hljs-built_in">SliverFixedExtentList</span>(
<span class="hljs-attribute">itemExtent</span>: <span class="hljs-number">150.0</span>,
<span class="hljs-attribute">delegate</span>: <span class="hljs-built_in">SliverChildListDelegate</span>(
[
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.red),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.purple),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.green),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.orange),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.yellow),
],
),
),
<span class="hljs-built_in">makeHeader</span>(<span class="hljs-string">'Header Section 3'</span>),
<span class="hljs-built_in">SliverGrid</span>(
<span class="hljs-attribute">gridDelegate</span>:
new <span class="hljs-built_in">SliverGridDelegateWithMaxCrossAxisExtent</span>(
<span class="hljs-attribute">maxCrossAxisExtent</span>: <span class="hljs-number">200.0</span>,
<span class="hljs-attribute">mainAxisSpacing</span>: <span class="hljs-number">10.0</span>,
<span class="hljs-attribute">crossAxisSpacing</span>: <span class="hljs-number">10.0</span>,
<span class="hljs-attribute">childAspectRatio</span>: <span class="hljs-number">4.0</span>,
),
<span class="hljs-attribute">delegate</span>: new <span class="hljs-built_in">SliverChildBuilderDelegate</span>(
(BuildContext context, int index) {
return new <span class="hljs-built_in">Container</span>(
<span class="hljs-attribute">alignment</span>: Alignment.center,
<span class="hljs-attribute">color</span>: Colors.teal[<span class="hljs-number">100</span> * (index % <span class="hljs-number">9</span>)],
<span class="hljs-attribute">child</span>: new <span class="hljs-built_in">Text</span>(<span class="hljs-string">'grid item $index'</span>),
);
},
<span class="hljs-attribute">childCount</span>: <span class="hljs-number">20</span>,
),
),
<span class="hljs-built_in">makeHeader</span>(<span class="hljs-string">'Header Section 4'</span>),
<span class="hljs-comment">// Yes, this could also be a SliverFixedExtentList. Writing </span>
<span class="hljs-comment">// this way just for an example of SliverList construction.</span>
<span class="hljs-built_in">SliverList</span>(
<span class="hljs-attribute">delegate</span>: <span class="hljs-built_in">SliverChildListDelegate</span>(
[
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.pink, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.cyan, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.indigo, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
<span class="hljs-built_in">Container</span>(<span class="hljs-attribute">color</span>: Colors.blue, <span class="hljs-attribute">height</span>: <span class="hljs-number">150.0</span>),
],
),
),
],
);
}
}</pre></div><p id="9dae">The last step (exercise left to the reader) would be to add a GestureDetector so that tapping on one of the headers allows you to jump to that section in the list. Take your newfound knowledge of Slivers and apply it to GestureDetection to make a cool collapsing list!</p></article></body>