Flutter ListView and Scrolling | Beginner's Tutorial
ListView is the most commonly used scrolling list Widget in Flutter, used to display scrollable content lists.
ListView Basic Usage
Example: ListView Basic Usage
// Method 1: children parameter (suitable for small number of items)
ListView(
children: [
ListTile(title: Text('Item 1')),
ListTile(title: Text('Item 2')),
ListTile(title: Text('Item 3')),
],
)
// Method 2: ListView.builder (suitable for large or infinite lists)
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
// Method 3: ListView.separated (with separators)
ListView.separated(
itemCount: 10,
separatorBuilder: (context, index) => const Divider(), // separator line
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
ListView Common Properties
| Property | Description |
|---|---|
| scrollDirection | Scroll direction, default is Axis.vertical (vertical) |
| reverse | Whether to reverse the scroll direction |
| padding | List inner padding |
| itemExtent | Fixed item height, can improve performance |
| prototypeItem | Prototype item, used to calculate height |
Example: Horizontal ListView
// Horizontal scrolling list
SizedBox(
height: 120, // Must set height
child: ListView.builder(
scrollDirection: Axis.horizontal, // Horizontal scroll
itemCount: 20,
itemBuilder: (context, index) {
return Container(
width: 100,
margin: const EdgeInsets.symmetric(horizontal: 8),
color: Colors.blue,
child: Center(
child: Text('Item $index'),
),
);
},
),
)
GridView - Grid Layout
GridView is used to create two-dimensional grid lists.
Example: GridView Usage
// GridView.count - Fixed number of columns
GridView.count(
crossAxisCount: 3, // 3 columns
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.blue,
child: Center(child: Text('${index + 1}')),
}),
)
// GridView.builder - Dynamic building
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, // 4 columns
mainAxisSpacing: 8, // Vertical spacing
crossAxisSpacing: 8, // Horizontal spacing
childAspectRatio: 1, // Aspect ratio
),
itemCount: 50,
itemBuilder: (context, index) {
return Container(
color: Colors.green,
child: Center(child: Text('${index + 1}')),
);
},
)
// GridView.extent - Adaptive number of columns
GridView.extent(
maxCrossAxisExtent: 150, // Maximum column width
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.orange,
child: Center(child: Text('${index + 1}')),
);
}),
)
Scroll Control
ScrollController can be used to control the scroll position.
Example: Scroll Control
class ScrollExample extends StatefulWidget {
const ScrollExample({super.key});
@override
State createState() => _ScrollExampleState();
}
class _ScrollExampleState extends State {
// Create scroll controller
late ScrollController _controller;
@override
void initState() {
super.initState();
_controller = ScrollController();
// Listen to scroll events
_controller.addListener(() {
print('Scroll position: ${_controller.offset}');
});
}
@override
void dispose() {
// Dispose controller
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
// Scroll to top button
ElevatedButton(
onPressed: () {
// Scroll to top
_controller.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: const Text('Scroll to Top'),
),
// List
Expanded(
child: ListView.builder(
controller: _controller, // Bind controller
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
),
),
],
);
}
}
Slivers Advanced Scrolling
CustomScrollView combined with Slivers can achieve more complex scrolling effects.
Example: Slivers Collapsing Effect
// Scroll view with collapsing app bar
CustomScrollView(
slivers: [
// Collapsing app bar
SliverAppBar(
expandedHeight: 200, // Expanded height
pinned: true, // Pin to top
flexibleSpace: FlexibleSpaceBar(
title: const Text('Collapsing Title'),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
),
),
// List content
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Item ${index + 1}')),
childCount: 30,
),
),
],
)
// Grid Sliver
CustomScrollView(
slivers: [
const SliverAppBar(
title: Text('Image Grid'),
pinned: true,
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
child: Image.network('https://picsum.photos/200?$index'),
),
childCount: 20,
),
),
],
)
Slivers provide an efficient way to handle large numbers of scrollable items, they only render items in the visible area, thus providing good performance.
YouTip