Flutter ListView und Scrollen
ListView ist das am häufigsten verwendete scrollbare Listen-Widget in Flutter und wird verwendet, um scrollbare Inhaltslisten anzuzeigen.
ListView Grundlegende Verwendung
Beispiel: ListView Grundlegende Verwendung
// Methode 1: children-Parameter (geeignet für eine kleine Anzahl von Elementen)
ListView(
children: [
ListTile(title: Text('First item')),
ListTile(title: Text('Second item')),
ListTile(title: Text('Third item')),
],
)
// Methode 2: ListView.builder (geeignet für große oder unendliche Listen)
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
// Methode 3: ListView.separated (mit Trennern)
ListView.separated(
itemCount: 10,
separatorBuilder: (context, index) => const Divider(), // Divider
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
ListView(
children: [
ListTile(title: Text('First item')),
ListTile(title: Text('Second item')),
ListTile(title: Text('Third item')),
],
)
// Methode 2: ListView.builder (geeignet für große oder unendliche Listen)
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
// Methode 3: ListView.separated (mit Trennern)
ListView.separated(
itemCount: 10,
separatorBuilder: (context, index) => const Divider(), // Divider
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
)
Allgemeine Eigenschaften von ListView
| Eigenschaft | Beschreibung |
|---|---|
| scrollDirection | Scrollrichtung, standardmäßig Axis.vertical (vertikal). |
| reverse | Ob umgekehrt gescrollt werden soll |
| padding | Listen-Padding |
| itemExtent | Feste Elementhöhe für bessere Performance |
| prototypeItem | Prototyp-Element zur Berechnung der Höhe |
Beispiel: Horizontale ListView
// Liste mit horizontalem Scrollen
SizedBox(
height: 120, // Höhe muss gesetzt werden
child: ListView.builder(
scrollDirection: Axis.horizontal, // Horizontales Scrollen
itemCount: 20,
itemBuilder: (context, index) {
return Container(
width: 100,
margin: const EdgeInsets.symmetric(horizontal: 8),
color: Colors.blue[100],
child: Center(
child: Text('Item $index'),
),
);
},
),
)
SizedBox(
height: 120, // Höhe muss gesetzt werden
child: ListView.builder(
scrollDirection: Axis.horizontal, // Horizontales Scrollen
itemCount: 20,
itemBuilder: (context, index) {
return Container(
width: 100,
margin: const EdgeInsets.symmetric(horizontal: 8),
color: Colors.blue[100],
child: Center(
child: Text('Item $index'),
),
);
},
),
)
GridView - Raster-Layout
GridView wird zum Erstellen zweidimensionaler Rasterlisten verwendet.
Beispiel: GridView-Verwendung
// GridView.count - feste Anzahl von Spalten
GridView.count(
crossAxisCount: 3, // 3 Spalten
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.blue[100],
child: Center(child: Text('${index + 1}')),
);
}),
)
// GridView.builder - dynamischer Aufbau
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, // 4 Spalten
mainAxisSpacing: 8, // Vertikaler Abstand
crossAxisSpacing: 8, // Horizontaler Abstand
childAspectRatio: 1, // Seitenverhältnis
),
itemCount: 50,
itemBuilder: (context, index) {
return Container(
color: Colors.green[100],
child: Center(child: Text('${index + 1}')),
);
},
)
// GridView.extent - adaptive Spaltenanzahl
GridView.extent(
maxCrossAxisExtent: 150, // Maximale Spaltenbreite
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.orange[100],
child: Center(child: Text('${index + 1}')),
);
}),
)
GridView.count(
crossAxisCount: 3, // 3 Spalten
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.blue[100],
child: Center(child: Text('${index + 1}')),
);
}),
)
// GridView.builder - dynamischer Aufbau
GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4, // 4 Spalten
mainAxisSpacing: 8, // Vertikaler Abstand
crossAxisSpacing: 8, // Horizontaler Abstand
childAspectRatio: 1, // Seitenverhältnis
),
itemCount: 50,
itemBuilder: (context, index) {
return Container(
color: Colors.green[100],
child: Center(child: Text('${index + 1}')),
);
},
)
// GridView.extent - adaptive Spaltenanzahl
GridView.extent(
maxCrossAxisExtent: 150, // Maximale Spaltenbreite
children: List.generate(20, (index) {
return Container(
margin: const EdgeInsets.all(4),
color: Colors.orange[100],
child: Center(child: Text('${index + 1}')),
);
}),
)
Scroll-Steuerung
Mit ScrollController können Sie die Scroll-Position steuern.
Beispiel: Scroll-Steuerung
class ScrollExample extends StatefulWidget {
const ScrollExample({super.key});
@override
State<ScrollExample> createState() => _ScrollExampleState();
}
class _ScrollExampleState extends State<ScrollExample> {
// Scroll-Controller erstellen
late ScrollController _controller;
@override
void initState() {
super.initState();
_controller = ScrollController();
// Auf Scroll-Ereignisse hören
_controller.addListener(() {
print('Scroll-Position: ${_controller.offset});
});
}
@override
void dispose() {
// Controller freigeben
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
// Schaltfläche zum Scrollen nach oben
ElevatedButton(
onPressed: () {
// Nach oben scrollen
_controller.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: const Text('Nach oben scrollen'),
),
// Liste
Expanded(
child: ListView.builder(
controller: _controller, // Controller binden
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
),
),
],
);
}
}
const ScrollExample({super.key});
@override
State<ScrollExample> createState() => _ScrollExampleState();
}
class _ScrollExampleState extends State<ScrollExample> {
// Scroll-Controller erstellen
late ScrollController _controller;
@override
void initState() {
super.initState();
_controller = ScrollController();
// Auf Scroll-Ereignisse hören
_controller.addListener(() {
print('Scroll-Position: ${_controller.offset});
});
}
@override
void dispose() {
// Controller freigeben
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
// Schaltfläche zum Scrollen nach oben
ElevatedButton(
onPressed: () {
// Nach oben scrollen
_controller.animateTo(
0,
duration: const Duration(milliseconds: 500),
curve: Curves.easeInOut,
);
},
child: const Text('Nach oben scrollen'),
),
// Liste
Expanded(
child: ListView.builder(
controller: _controller, // Controller binden
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(title: Text('Item ${index + 1}'));
},
),
),
],
);
}
}
Slivers: Fortgeschrittenes Scrollen
CustomScrollView in Kombination mit Slivers kann komplexere Scrolleffekte erzielen.
Beispiel: Kollabierender Slivers-Effekt
// Scroll-Ansicht mit einklappbarer App-Leiste
CustomScrollView(
slivers: [
// App-Leiste einklappen
SliverAppBar(
expandedHeight: 200, // Ausgeklappte Höhe
pinned: true, // Oben fixiert
flexibleSpace: FlexibleSpaceBar(
title: const Text('Einklappbarer Titel'),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
),
),
// Listeninhalt
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Element ${index + 1}')),
childCount: 30,
),
),
],
)
// Raster-Sliver
CustomScrollView(
slivers: [
const SliverAppBar(
title: Text('Bildraster'),
pinned: true,
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
child: Image.network('https://picsum.photos/200?$index'),
),
childCount: 20,
),
),
],
)
CustomScrollView(
slivers: [
// App-Leiste einklappen
SliverAppBar(
expandedHeight: 200, // Ausgeklappte Höhe
pinned: true, // Oben fixiert
flexibleSpace: FlexibleSpaceBar(
title: const Text('Einklappbarer Titel'),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue, Colors.purple],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
),
),
),
// Listeninhalt
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) => ListTile(title: Text('Element ${index + 1}')),
childCount: 30,
),
),
],
)
// Raster-Sliver
CustomScrollView(
slivers: [
const SliverAppBar(
title: Text('Bildraster'),
pinned: true,
),
SliverGrid(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
delegate: SliverChildBuilderDelegate(
(context, index) => Card(
child: Image.network('https://picsum.photos/200?$index'),
),
childCount: 20,
),
),
],
)
Weitere ErweiterungenSlivers bieten einen effizienten Weg, eine große Anzahl scrollender Elemente zu handhaben; sie rendern nur Elemente im sichtbaren Bereich und bieten dadurch eine gute Leistung.