Woah! I've spent several hours refactoring nested ListViews to a parent CustomScrollView & child Slivers. The errors Slivers produced were opaque and frightening, with nothing illuminating in Logcat; sleuthing devoured much of the time.
Anyway, that's solved. I find I still have jank scrolling a 15-item list. OK, each item can involve further numerous widgets {Padding, Alignment, Elevated button, Row, Text, SizedBox, Icon}. So my 15-item list ends up being multiple more Widgets.
I've now swapped out my SliverChildListDelegate for SliverChildBuilderDelegates, so a Builder builds the Widget List lazily. Having done this, it seems quite inefficient because it's increased the Widgets in the Widget tree. Each of the builders' buildItem() calls needs an extra Column Widget to wrap that sub-chunk of the total list.
It may be a lot of Widgets scrolling but it's only a 15 item list. I wish I knew what to optimise. Any thoughts on how to best reduce jank on Lists for mobile web?
The Flutter team says Flutter works best for computational-centred apps rather than text heavy informational apps. In future would it be better just to use webView Widgets? I always thought embedding Webviews would be clunky and slow but Lists of native Flutter Widgets, even as SliverLists, give jank.
Here is the janky list complete with builder:
Widget buildLocationDescriptionWidgets(LocationDetails presentLocation) {
print(LOG + "buildLocationDescriptionWidgets");
if (presentLocation.descriptionLinkUrls.isEmpty)
return SliverToBoxAdapter(child:
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
child: Text(presentLocation.description[0])));
int numDescriptionBlocks = presentLocation.description.length;
double paddingBottom = 16;
if (presentLocation.descriptionLinkUrls.length >= numDescriptionBlocks) {
paddingBottom = 0;
}
return SliverPadding(
padding: EdgeInsets.fromLTRB(16, 16, 16, paddingBottom), sliver:
SliverList(
key: Key("descriptionSliverList"),
delegate: SliverChildBuilderDelegate((context, index) =>
buildDescriptionBlock(context, index),
childCount: presentLocation.description.length
),
));
}
Column buildDescriptionBlock(BuildContext context, int index) {
List<Widget> colChildWidget = [];
colChildWidget.add(Text(
widget.presentLocation.description[index],
textAlign: TextAlign.left,
));
if (index < widget.presentLocation.descriptionLinkUrls.length) {
colChildWidget.add(Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Align(
alignment: Alignment.center,
child: index >=
widget.presentLocation.descriptionButtonIcons.length
? ElevatedButton(
child: Text(
widget.presentLocation.descriptionButtonText[index]),
onPressed: () {
_launchURL(
widget.presentLocation.descriptionLinkUrls[index]);
})
: ElevatedButton(
child:
Row(mainAxisSize: MainAxisSize.min, children: [
Text(
widget.presentLocation.descriptionButtonText[index]),
SizedBox(width: 8),
FaIcon(
buttonIconMap[widget.presentLocation
.descriptionButtonIcons[index]],
size: 16)
]),
onPressed: () {
_launchURL(
widget.presentLocation.descriptionLinkUrls[index]);
}))));
}
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: colChildWidget);
}
Should I regress from a builder to a conventional SliverList?
Other things I've tried: I eliminated jank in my app Drawer list by putting const everywhere possible, lots of Dividers were made Const. But when you style text using Theme.of(context).textTheme.bodyText2
etc. it doesn't allow you to set textboxes to const. If you want to use const
you can't style the app globally, you'd have to hard code. Is it worth forsaking abstraction for hard coding Text widget styles?
Here is the web app: Love Edinburgh
For the clearest example of jank
- Open the App Drawer
- Scroll to WONDER
- Tap Arthur's Seat
- Open the panel to full screen - slide it up
- Scroll down the panel.
It doesn't show on a desktop browser which is compiled using Skia / Webkit. It's a bit fiddly to get scroll working on a desktop browser, you need to click amongst the text, then attempt to scroll. It's meant for mobile use so I'm resigned to that.