On Part 1, I made the working version of the Escapists Crafting Guide app using Flutter. I used ListView
widget to show the different tools and items available for crafting.
Today I am going to improve the app slightly by showing on the list the category where these tools belong. I am also going to replace the ListView
with SliverList
— I describe it as a fancier list view. I am also exploring flutter_sticky_header
[repository] [pub.dev] to achieve the behavior when the user scrolls and the category sticks to the top until the next category is in the current view. I will also be polishing the design along the way.
Categories of tools source: Gamepedia The Escapists Crafting Guide
SliverList
To use the SliverList, it needs to be wrapped on a CustomScrollView
which comes with the familiar API that we already learned from using ListView
with slight changes. This widget requires a list of children widgets called slivers
.
A sliver is a portion of a scrollable area. A sliver could be a SliverAppBar, SliverList, or a SliverGrid.
Data structure
Previously, I was just working with a linear list of all items. Right now I need to refactor it to group the tools by categories.
My input data contains a list of items, and for each item it has a category.
[
{
"name": "Flimsy Pickaxe",
"category": "Tools"
},
{
"name": "Lightweight Pickaxe",
"category": "Tools",
},
{
"name": "Cup of Molten Chocolate",
"category": "Weapon"
}
]
A function is required to create a map
data structure of the tools. The map will then be used to build the slivers. The slivers will contain the category as the header — the one that sticks to the top when scrolled, and then followed by the rest of the items belonging to the category.
Map categorizeItems(items) {
var categories = Map();
items.forEach((element) {
if (!categories.containsKey(element.category)) {
categories[element.category] = List();
}
categories[element.category].add(element);
});
return categories;
}
Sticky header
I am using flutter_sticky_header
to achieve the sticky header effect. First, update pubspec.yaml
.
dependencies:
flutter_sticky_header: ^0.5.0
Then run flutter pub get
.
The basic structure looks like below. Each one of this is a child of the CustomScrollView.slivers
SliverStickyHeader(
header: Header(title: category),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return InkWell(
child: ItemCard(data: items[index]),
onTap: () {...}
);
},
childCount: items.length,
), // SliverChildBuilderDelegate
), // SliverList
)
The resulting code looks like the following.
Conclusion
Now, I have finally ticked off an improvement. Will continue to do more.
- A separator between categories on the list view
Next, I will be using another sliver to achieve a feature that I always wanted to have — a complete spread or a tree, not just the immediate requirements, to show all components required to craft a tool.
Until next time!
References
- SliverList class https://api.flutter.dev/flutter/widgets/SliverList-class.html
- Using slivers to achieve fancy scrolling https://flutter.dev/docs/development/ui/advanced/slivers
- Dart Maps https://dart.dev/guides/language/language-tour#maps