Sticky Header Flutter Example
In this article, we are going to integrate sticky header view in listview in flutter application. You can also check flutter listview related articles.
In this flutter example, we are displaying football clubs names with associated players names. We show football club name as sticky header in flutter list view. Football players names are displayed below each related club name sticky header row. We will not place listview inside listview to display player names with their clubs. We will add players names as dynamic widget to children property of column inside listview.
Add required package in pubspec.yaml file
Types of Sticky Header
import ‘package:flutterstickyheadersample/my_animated_sticky_header_screen.dart’;
import ‘package:flutterstickyheadersample/my_overlapped_sticky_header_screen.dart’;
import ‘package:flutterstickyheadersample/my_simple_sticky_header_screen.dart’;
class MyStickyHeaderScreen extends StatefulWidget {
@override
_MyStickyHeaderScreenState createState() => _MyStickyHeaderScreenState();
}
class _MyStickyHeaderScreenState extends State<MyStickyHeaderScreen> {
HashMap<String, List<String>> mapSoccerPlayers =
HashMap<String, List<String>>();
@override
void initState() {
super.initState();
mapSoccerPlayers[‘Manchester United’] = [
‘Cristiano Ronaldo’,
‘Bruno Fernandes’
];
mapSoccerPlayers[‘Manchester City’] = [‘Kevin De Bruyne’];
mapSoccerPlayers[‘Liverpool’] = [
‘Virgil van Dijk’,
‘Mohamed Salah’,
‘Trent Alexander-Arnold’
];
mapSoccerPlayers[‘Chelsea’] = [‘Romelu Lukaku’, ‘Thiago Silva’];
mapSoccerPlayers[‘Tottenham’] = [‘Harry Kane’, ‘Son Heung-min’];
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(‘Flutter Stickey Header Sample’)),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.orangeAccent,
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 15)),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
MySimpleStickyHeaderScreen(mapSoccerPlayers)));
},
child: Text(‘Simple Sticky Header’,
style: TextStyle(
fontSize: 22, fontWeight: FontWeight.bold))),
SizedBox(height: 25),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.redAccent,
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 15)),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
MyAnimatedStickyHeaderScreen(mapSoccerPlayers)));
},
child: Text(‘Animated Sticky Header’,
style: TextStyle(
fontSize: 22, fontWeight: FontWeight.bold))),
SizedBox(height: 25),
ElevatedButton(
style: ElevatedButton.styleFrom(
primary: Colors.deepOrangeAccent,
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 15)),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
MyOverlappedStickyHeaderScreen(mapSoccerPlayers)));
},
child: Text(‘Overlapped Sticky Header’,
style: TextStyle(
fontSize: 22, fontWeight: FontWeight.bold))),
],
),
));
}
}

Simple Sticky Header
import ‘package:flutter/material.dart’;
import ‘package:sticky_headers/sticky_headers.dart’;
class MySimpleStickyHeaderScreen extends StatelessWidget {
HashMap<String, List<String>> mapSoccerPlayers =
HashMap<String, List<String>>();
ScrollController myScrollContainer = ScrollController();
MySimpleStickyHeaderScreen(this.mapSoccerPlayers);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(‘Simple Sticky Header’)),
body: Container(
child: ListView.builder(
primary: myScrollContainer == null,
controller: myScrollContainer,
itemCount: mapSoccerPlayers.keys.length,
itemBuilder: (context, index) {
String getKey = mapSoccerPlayers.keys.toList()[index];
List<String> getValuesFromKey = mapSoccerPlayers[getKey];
List<Widget> listPlayerNamesWidgets = [];
for (var playerName in getValuesFromKey) {
listPlayerNamesWidgets.add(Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Text(
playerName,
style: TextStyle(fontSize: 25),
)));
}
return Material(
child: StickyHeader(
controller: myScrollContainer,
header: Container(
height: 60,
color: Colors.orangeAccent,
padding: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
child: Text(
getKey,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: listPlayerNamesWidgets,
)),
);
},
),
),
);
}
}


Animated Header for List View
import ‘package:flutter/material.dart’;
import ‘package:sticky_headers/sticky_headers.dart’;
class MyAnimatedStickyHeaderScreen extends StatelessWidget {
HashMap<String, List<String>> mapSoccerPlayers =
HashMap<String, List<String>>();
ScrollController myScrollContainer = ScrollController();
MyAnimatedStickyHeaderScreen(this.mapSoccerPlayers);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(‘Animated Sticky Header’)),
body: Container(
child: ListView.builder(
primary: myScrollContainer == null,
controller: myScrollContainer,
itemCount: mapSoccerPlayers.keys.length,
itemBuilder: (context, index) {
String getKey = mapSoccerPlayers.keys.toList()[index];
List<String> getValuesFromKey = mapSoccerPlayers[getKey];
List<Widget> listPlayerNamesWidgets = [];
for (var playerName in getValuesFromKey) {
listPlayerNamesWidgets.add(Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Text(
playerName,
style: TextStyle(fontSize: 25),
)));
}
return Material(
child: StickyHeaderBuilder(
controller: myScrollContainer, // Optional
builder: (BuildContext context, double stuckAmount) {
stuckAmount = 1.0 – stuckAmount.clamp(0.0, 1.0);
return Container(
height: 60,
color: Color.lerp(Colors.orangeAccent,
Colors.pinkAccent, stuckAmount),
padding: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
child: Row(
children: <Widget>[
Expanded(
child: Text(
getKey,
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
Offstage(
offstage: stuckAmount <= 0.0,
child: Opacity(
opacity: stuckAmount,
child: IconButton(
icon: Icon(Icons.favorite, color: Colors.white),
onPressed: () => ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
content: Text(
getKey + ‘ is selected as favorite’,
style: TextStyle(fontWeight: FontWeight.bold),
))),
),
),
),
],
),
);
},
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: listPlayerNamesWidgets,
)),
);
},
),
),
);
}
}


Overlapped Sticky Header in Flutter
import ‘package:flutter/material.dart’;
import ‘package:sticky_headers/sticky_headers.dart’;
class MyOverlappedStickyHeaderScreen extends StatelessWidget {
HashMap<String, List<String>> mapSoccerPlayers =
HashMap<String, List<String>>();
ScrollController myScrollContainer = ScrollController();
MyOverlappedStickyHeaderScreen(this.mapSoccerPlayers);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(‘Overlapped Sticky Header’)),
body: Container(
child: ListView.builder(
primary: myScrollContainer == null,
controller: myScrollContainer,
itemCount: mapSoccerPlayers.keys.length,
itemBuilder: (context, index) {
String getKey = mapSoccerPlayers.keys.toList()[index];
List<String> getValuesFromKey = mapSoccerPlayers[getKey];
List<Widget> listPlayerNamesWidgets = [];
for (var playerName in getValuesFromKey) {
listPlayerNamesWidgets.add(Padding(
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Text(
playerName,
style: TextStyle(fontSize: 25),
)));
}
return Material(
child: StickyHeaderBuilder(
overlapHeaders: true,
controller: myScrollContainer, // Optional
builder: (BuildContext context, double stuckAmount) {
stuckAmount = 1.0 – stuckAmount.clamp(0.0, 1.0);
return Container(
height: 60,
color: Colors.deepOrangeAccent.withOpacity(0.6 + stuckAmount * 0.4),
padding: EdgeInsets.symmetric(horizontal: 16),
alignment: Alignment.centerLeft,
child: Text(
getKey,
style: TextStyle(
fontSize: 25,
color: Colors.white),
),
);
},
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: listPlayerNamesWidgets,
)),
);
},
),
),
);
}
}

Pingback: Flutter List View with Different Types of Items - CodingWithDhrumil