Flexible lists
We've previously looked into rows and columns that can be used to create fixed rows and columns. There is a need for more flexible layouts widgets, however, such as widgets that span outside of the screen or that can be scrolled.
One such widget is ListView, which allows creating scrollable content.
The following example demonstrates the use of ListView with three children.
When you launch the application, depending on the size of the screen of the device you use, not all of the containers are visible at the same time. You can scroll the content e.g. by using the finger, depending again on the device (scrolling with the mouse is disabled by default).
Scroll direction
By default, ListView widgets are vertically aligned (i.e. stacked on top of each other). The direction can be changed using the scrollDirection
-argument, which takes an Axis as a value. The available values are Axis.horizontal
and Axis.vertical
.
To change the application so that the scroll direction is horizontal, we set the value of the scrollDirection
argument of the ListView to Axis.horizontal
.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: Scaffold(
body: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(color: Colors.red, height: 250),
Container(color: Colors.yellow, height: 250),
Container(color: Colors.green, height: 250),
],
))));
}
When we try out the above example, we notice that it does not work, however.
Containers and limiting space
ListView packs the contents given to it and thus minimizes the space available to its children. In the previous example, as we had not explicitly defined the width of the container widgets, the width of each container is minimized, and they end up not being visible at all.
This can be fixed by defining a width for the widgets. In the following example, the widgets have a width of 250 pixels each.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: Scaffold(
body: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(color: Colors.red, height: 250, width: 250),
Container(color: Colors.yellow, height: 250, width: 250),
Container(color: Colors.green, height: 250, width: 250),
],
))));
}
Now, when we try out the application, the issue has been fixed. We, however, notice that the height of the containers is certainly not just 250 pixels.
ListView size and scroll direction
The above observation stems from the way how ListView is implemented. ListView maximizes height and minimizes width when the scrollDirection
argument is set to Axis.horizontal
. However, when used with Axis.vertical
(default setting), the height is minimized and instead, the width is maximized.
This behavior also overrides properties that could be inferred from child components. That is, even though we set the height to 250 pixels in the containers that are inside of a horizontal ListView, the height is not 250.
Defining the height of a horizontal ListView
If we wish to set the height of a horizontal ListView, we use a container to define the available height. The following example demonstrates this.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: Scaffold(
body: Container(
height: 250,
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(color: Colors.red, width: 250),
Container(color: Colors.yellow, width: 250),
Container(color: Colors.green, width: 250),
],
),
))));
}
Defining the width of a vertical ListView
Similarly, if we wish to set the width of a vertical ListView, we use a container to define the available width. The following example demonstrates this.
import 'package:flutter/material.dart';
main() {
runApp(MaterialApp(
home: Scaffold(
body: Container(
width: 250,
child: ListView(
children: [
Container(color: Colors.red),
Container(color: Colors.yellow),
Container(color: Colors.green),
],
),
))));
}
When you test the application, you notice again that nothing is visible. When we recall that a vertical ListView maximizes width but minimizes height, we can see the reason: the height of the containers is not set, and thus the height is minimized.
The following example fixes this issue.
Plenty of widgets!
We are slowly learning about more widgets. To summarize what we have learned so far, Container widgets are used to create an area into which another widget can be placed. ListView, Row, and Column are used to create rows and columns, and the space available for widgets within them can be influenced using Expanded and SizedBox. ListTile widgets can be further used to group contents, and Card widgets provide easy styling.
The example below demonstrates one possible way of creating a layout for a somewhat larger application. The structure of the application in a tree-like format would be as follows, while the source code is below the tree-like format. The application also shows spacing of widgets using mainAxisAlignment
.
In practice, in the case of such an application, we would decompose the application into smaller widgets where each would have a specific responsibility.