We said that the Flutter scroll control is ListView

A GridView, unlike a ListView, can build a two-dimensional list of grids.

By the way, the CustomScrollView

GridView

The source code example

Constructors are as follows:

GridView({ Axis scrollDirection = Axis.vertical, bool reverse = false, ScrollController controller, bool primary, ScrollPhysics physics, bool shrinkWrap = false, EdgeInsetsGeometry padding, @required SliverGridDelegate gridDelegate, Bool addAutomaticKeepAlives = true, bool addRepaintBoundaries = true, double cacheExtent, List<Widget> children = const <Widget>[], })Copy the code

Attribute interpretation

As you can see, most properties of the GridView are the same as those of the ListView, and they all have the same meaning. If you don’t know, click on the Flutter scroll control TAB –>ListView

gridDelegate

The gridDelegate is of type SliverGridDelegate and controls how the child components of the GridView are arranged.

SliverGridDelegate is an abstract class, A subclass of Flutter provides two SliverGridDelegate SliverGridDelegateWithFixedCrossAxisCount and SliverGridDelegateWithMaxCrossAxisExtent, We can use them directly. Here’s a look at them.

SliverGridDelegateWithFixedCrossAxisCount

This subclass implements a layout algorithm with a fixed number of child elements on the horizontal axis,

The source code example

Constructors are as follows:

SliverGridDelegateWithFixedCrossAxisCount({
  @required double crossAxisCount, 
  double mainAxisSpacing = 0.0,
  double crossAxisSpacing = 0.0,
  double childAspectRatio = 1.0,
})
Copy the code

Attribute interpretation

crossAxisCount

This property represents the number of child elements on the horizontal axis. The child’s horizontal length is determined by dividing the ViewPort’s horizontal length by crossAxisCount.

mainAxisSpacing

This property represents the spacing along the main axis.

crossAxisSpacing

Represents the spacing of child elements along the horizontal axis.

childAspectRatio

Represents the ratio of the length of the child element along the horizontal axis to the length of the main axis. Since crossAxisCount is specified, the length of the child along the axis is determined, and then the length of the child along the axis is determined by this parameter value.

Code sample

The GridView (gridDelegate: SliverGridDelegateWithFixedCrossAxisCount (crossAxisCount: 3, / / transverse three child widgets childAspectRatio: 1.0 // Width ratio 1, child widget), children: <Widget>[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive,color: Colors.red,), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast) ])Copy the code

Operation effect:

GridView.count

The GridView. Count used SliverGridDelegateWithFixedCrossAxisCount inside the constructor, through which we can quickly create transverse fixed number of child elements of the GridView,

The sample code above is equivalent to:

GridView.count(
	crossAxisCount: 3,
	childAspectRatio: 1.0,
	children: <Widget>[
	  Icon(Icons.ac_unit),
	  Icon(Icons.airport_shuttle),
	  Icon(Icons.all_inclusive,color: Colors.red,),
	  Icon(Icons.beach_access),
	  Icon(Icons.cake),
	  Icon(Icons.free_breakfast),
	],
)
Copy the code

SliverGridDelegateWithMaxCrossAxisExtent

This subclass implements a layout algorithm with a fixed maximum length of children on the horizontal axis,

The source code example

Constructors are as follows:

SliverGridDelegateWithMaxCrossAxisExtent ({double maxCrossAxisExtent, double mainAxisSpacing = 0.0, Double crossAxisSpacing = 0.0, double childAspectRatio = 1.0,})Copy the code

Attribute interpretation

maxCrossAxisExtent

MaxCrossAxisExtent is the maximum length of a child element along the horizontal axis, which is the “maximum” length because the length of each child element along the horizontal axis is still equally divided.

For example, if the ViewPort has a horizontal length of 450, the child elements will end up being 112.5 when maxCrossAxisExtent is within the range of 450/4, 450/3. The ratio of the horizontal axis to the main axis of the child element indicated by childAspectRatio is the final length ratio.

Other parameters is the same as the SliverGridDelegateWithFixedCrossAxisCount.

Code sample

GridView( padding: EdgeInsets.zero, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( maxCrossAxisExtent: ChildAspectRatio: 2.0 childAspectRatio: 2.0 <Widget>[ Icon(Icons.ac_unit), Icon(Icons.airport_shuttle), Icon(Icons.all_inclusive), Icon(Icons.beach_access), Icon(Icons.cake), Icon(Icons.free_breakfast), ], )Copy the code

Operation effect:

GridView.extent

The GridView. Among the constructor for internal use SliverGridDelegateWithMaxCrossAxisExtent, through which we can quickly create a longitudinal axis element for a fixed maximum length of the GridView.

The sample code above is equivalent to:

GridView.extent(
	maxCrossAxisExtent: 100.0,
	childAspectRatio: 2.0,
	children: <Widget>[
	  Icon(Icons.ac_unit),
	  Icon(Icons.airport_shuttle),
	  Icon(Icons.all_inclusive),
	  Icon(Icons.beach_access),
	  Icon(Icons.cake),
	  Icon(Icons.free_breakfast),
	],
)
Copy the code

GridView.builder

Like ListView, children only works with a small number of child components, and when there are many, we can create them dynamically using gridView.Builder.

The source code example

Constructors are as follows:

GridView.builder(
 ...
 @required SliverGridDelegate gridDelegate, 
 @required IndexedWidgetBuilder itemBuilder,
)
Copy the code

Attribute interpretation

The gridDelegate property says that there is only one itemBuilder, which is the builder of the child component.

Code sample

Suppose we need to batch some ICONS from an asynchronous data source, such as a network, and display them in a GridView:

import 'package:flutter/material.dart'; class CategoryPage extends StatefulWidget { @override _CategoryPageState createState() => _CategoryPageState(); } class _CategoryPageState extends State<CategoryPage> { List<IconData> _icons = []; // Save the Icon data @override void initState() {// Initialize the data _retrieveIcons(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("GridView")), body: The GridView. Builder (gridDelegate: SliverGridDelegateWithFixedCrossAxisCount (crossAxisCount: 3, / / three columns in a row childAspectRatio: 1.0 // Display area width and height equal), itemCount: _icons. Length, itemBuilder: (context, If (index == _icons.length - 1 && _icons.length < 100) {_retrieveIcons(); } return Icon(_icons[index]); })); } // void _retrieveIcons() {fut.delayed (Duration(milliseconds: 200)).then((e) { setState(() { _icons.addAll([ Icons.ac_unit, Icons.airport_shuttle, Icons.all_inclusive, Icons.beach_access, Icons.cake, Icons.free_breakfast ]); }); }); }}Copy the code

_retrieveIcons() : In this method we simulate retrieving data from an asynchronous data source through future.delayed, each retrieving takes 200 milliseconds, new data is added to _icons after successful retrieval, and then setState is called to rebuild.

In the itemBuilder, if the last item is displayed, determine if you need to continue retrieving the data and return an Icon.

Operation effect:

supplement

The GridView of Flutter defaults to equal display space for child elements, but in real development you may encounter situations where child elements are of unequal sizes.

As shown in figure:

Pub. dev has a package called Flutter_staggered_grid_view, which implements a staggered GridView layout model that can be easily implemented.

CustomScrollView

CustomScrollView is a component that can customize a scroll model (effect) using Sliver, and it can contain multiple scroll models.

Suppose you have a page that needs a GridView at the top and a ListView at the bottom, and you want the entire page to slide uniformly, that is, to look like a whole. If you use GridView+ListView, you can’t guarantee a consistent slide because the scrollability is separate, so you need a glue to glue the separate scrollable components together, and CustomScrollView acts as the glue.

Sliver version of scrollable components

A Sliver, as mentioned earlier, can mean a small piece or slice. In Flutter, a Sliver usually refers to a scrollable component child element (like a slice). But in the case of CustomScrollView, the scrollable component that needs to be glued is the Sliver of CustomScrollView.

It is not possible to use the ListView and GridView as a CustomScrollView because they are scrollable components and not slivers!

Therefore, to make the scrollable components work with the CustomScrollView, Flutter provides Sliver versions of scrollable components, such as SliverList, SliverGrid, etc. In fact, the biggest difference between Sliver scrollable components and non-Sliver scrollable components is that Sliver does not contain a scroll model (the child body can no longer be scrollable), while Sliver does contain a scroll model. This is why CustomScrollView can “glue” multiple slivers together. These slivers share the Scrollable of the CustomScrollView, so a uniform sliding effect is achieved.

One thing to note:CustomScrollViewThe child components of must all be Slivers.

Code sample

import 'package:flutter/material.dart'; class CategoryPage extends StatefulWidget { @override _CategoryPageState createState() => _CategoryPageState(); } class _CategoryPageState extends State<CategoryPage> { @override Widget build(BuildContext context) { return Material( Child: CustomScrollView(slivers: <Widget>[//AppBar, including a navigation bar SliverAppBar(pinned: true, expandedHeight: FlexibleSpace: FlexibleSpaceBar(title: const Text('Demo'), background: image.asset ("images/ test.jpg ", fit: flexibleSpace: FlexibleSpaceBar(title: const Text('Demo'), background: image.asset ("images/ test.jpg ", fit: Box-fit.cover,),),), SliverPadding(padding: const EdgeInsets. All (8.0), sliver: new SliverGrid(//Grid gridDelegate: New SliverGridDelegateWithFixedCrossAxisCount (crossAxisCount: 2, / / Grid according to the two columns show mainAxisSpacing: 10.0, crossAxisSpacing: 10.0, childAspectRatio: 4.0,), delegate: New SliverChildBuilderDelegate (BuildContext context, int index) {/ / create a widget return new Container (alignment: Alignment.center, color: Colors.cyan[100 * (index % 9)], child: new Text('grid item $index'), ); }, childCount: //List new SliverFixedExtentList(itemExtent: 50.0, delegate: New SliverChildBuilderDelegate (BuildContext context, int index) {/ / to create a list item return new Container (alignment: Alignment.center, color: Colors.lightBlue[100 * (index % 9)], child: new Text('list item $index'), ); }, childCount: 50 //50 list items),),],),); }}Copy the code

The code is divided into three parts:

  • Header SliverAppBar: SliverAppBar corresponds to AppBar, the difference being that SliverAppBar can be integrated into CustomScrollView. SliverAppBar can be combined with FlexibleSpaceBar to implement flexible header models in Material Design.

  • Middle SliverGrid: It wraps with SliverPadding to add padding to the SliverGrid. The SliverGrid is a two-column, aspect ratio 4 grid with 20 child components.

  • Bottom SliverFixedExtentList: This is a list with all child elements 50 pixels high.

Operation effect:


X_X