ListView in Flutter
Listing is an important feature in mobile application development. Many times we need to design list of items that can be scrolled. ListView widget allows to create scrollable list.
Let’s understand ListView with small recipe app :
recipeList is list of objects of class Recipe
class Recipe {
String name;
String image;
String ingredients;
String recipe;
Recipe({this.image, this.name, this.ingredients, this.recipe});
}
List<Recipe> recipeList = [
Recipe(....),
Recipe(....),
Recipe(....),
Recipe(....),
Recipe(....),
Recipe(....),
Recipe(....),
Recipe(....),
];
To create a ListView, constructor of ListView widget is used.
ListView widget has 4 constructors
- ListView
This is a default constructor. This default constructor is used to write list of items to make it scrollable.
Syntax:
ListView(
children: <Widget>[
ListItemOne(),
ListItemTwo(),
ListItemThree(),
],
)
ListView default constructor is used when there are small number of items in list.
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 60,
width: 600,
child: ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: false,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 60,
width: 150,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10)),
child: Center(
child: Text(
"Sweets",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
)),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 60,
width: 150,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10)),
child: Center(
child: Text(
"Rice",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
)),
),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: Container(
height: 60,
width: 150,
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10)),
child: Center(
child: Text(
"Curry",
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.bold),
)),
),
),
],
)),
),
2. ListView.builder
builder() constructor constructs the list lazily. It means, it builds a list only for that portion which is visible on screen.
Syntax:
ListView.builder(
itemCount: recipeList.length,
itemBuilder:(context, index) {
return ListOFItems();
},
)
itemCount specifies length of list.
itemBuilder builds the indexed list of items.
We can use ListView.builder for indefinite list items.
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 200,
width: 600,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: recipeList.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
Procedure(recipeList[index])));
},
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
width: 150,
height: 150,
child: Image.network(
recipeList[index].image,
fit: BoxFit.fill,
),
),
),
Text(
recipeList[index].name,
style: TextStyle(
fontSize: 20, fontWeight: FontWeight.w700),
)
],
),
);
}),
),
),
3. ListView.separated
separated() constructor builds a list in which each list item separated by separator item.
Syntax:
ListView.separated(
itemCount: recipeList.length,
itemBuilder: (context, index) {
return ListOFItem();
},
separatorBuilder: (context, index) {
return SeparatorItem();
},
),
here itemCount specifies length of list.
itemBuilder builds a indexed list of items.
separatorBuilder builds separator Item that we want to insert in above index list.
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 600,
width: screenWidth,
child: ListView.separated(
scrollDirection: Axis.vertical,
itemCount: recipeList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => Procedure(recipeList[index])));
},
child: Card(
child: Row(
children: <Widget>[
Image.network(
recipeList[index].image,
height: 100,
width: 100,
fit: BoxFit.fill,
),
SizedBox(
width: 10,
),
Text(
recipeList[index].name,
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.w700,
decoration: TextDecoration.underline),
),
],
),
),
);
},
separatorBuilder: (context, index) {
return SizedBox(
child: Divider(
thickness: 1,
endIndent: 2,
indent: 1,
color: Colors.blue,
),
);
},
),
),
),
Divider is used as a separator here.
4. ListView.custom
As the name suggest custom() constructor allows us to design list as per our need.
Syntax:
ListView.custom(
childrenDelegate: SliverChildBuilderDelegate((context, index) {
return ListOFItem();
},
)
the main property in custom() constructor is childrenDelegate, it takes 2 parameters
SilverChildListDelegate, allows to define list of items.
SliverChildBuilderDelegate, allows to create indexed list of items.
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 200,
child: ListView.custom(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
childrenDelegate: SliverChildBuilderDelegate(
(context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
Procedure(recipeList[index])));
},
child: Text(
recipeList[index].name,
style: TextStyle(
fontSize: 17,
color: Colors.redAccent,
fontWeight: FontWeight.w700,
decoration: TextDecoration.underline),
),
);
},
childCount: recipeList.length,
),
),
),
),
here childCount gives us length of list.
childCount is always associated with SliverChildBuilderDelegate.
Some common Properties of ListView:
itemCount: to specify length of list.
itemBuilder: to build indexed list of items.
scrollDirection: to define axis for scroll list.
reverse: direction to display list items.
shrinkWrap: true, allows ListView only occupies the space that it needs.
physics, allows to make list scrollable or not.
it has two values as, AlwaysScrollableScrollPhysics() to allow scrolling,
NeverScollableScrollPhysics(), to stop scrolling,
Here is final output :
please visit GitHub for complete project :
https://github.com/yogitakumar/listview_demo
Thank You!