In Flutter, scrolling to a specific widget within a Listview
can be achieved through various methods. However, the most straightforward approach is often overlooked due to its simplicity.
The Easy Solution: Scrollable.ensureVisible(context)
The easiest solution to scroll to a specific widget in a ListView is by using Scrollable.ensureVisible(context)
. This method does everything for you and works with any widget size. To fetch the context, you can use a GlobalKey.
final dataKey = new GlobalKey();
// ...
Scrollable.ensureVisible(dataKey.currentContext);
Code language: PHP (php)
However, this approach may not work as expected due to how ListView handles rendering non-visible items. When ListView doesn’t render an item that’s not visible on the screen, it means your target widget won’t be built at all, leaving you without a context to use with Scrollable.ensureVisible
.
The Problem: Non-Rendered Items in ListView
As mentioned earlier, ListView doesn’t render items that are not visible on the screen. This means your target widget will likely not be built when using Scrollable.ensureVisible(context) directly.
A Better Solution: Replacing ListView with SingleChildScrollView and a Column
A more reliable solution is to replace your ListView with a SingleChildScrollView and wrap your children in a Column. Here’s an example:
class ScrollView extends StatelessWidget {
final dataKey = new GlobalKey();
@override
Widget build(BuildContext context) {
return new Scaffold(
primary: true,
appBar: new AppBar(
title: const Text('Home'),
),
body: new SingleChildScrollView(
child: new Column(
children: <widget>[
// ...
new Card(
key: dataKey,
child: new Text("data\n\n\n\n\n\ndata"),
)
],
),
),
bottomNavigationBar: new RaisedButton(
onPressed: () => Scrollable.ensureVisible(dataKey.currentContext),
child: new Text("Scroll to data"),
),
);
}
}
</widget>
Code language: PHP (php)
Note that this approach is not recommended for large, predefined lists due to performance issues. However, it’s a viable solution for small lists.
Using ScrollablePositionedList for ListView with scrollToIndex() Functionality
If you need the scrollToIndex() functionality and don’t mind using a different kind of ListView, you can use ScrollablePositionedList instead. This widget does support scrollToIndex() and offers an ItemScrollController that provides jumpTo() and scrollTo() methods.
ItemScrollController _scrollController = ItemScrollController();
ScrollablePositionedList.builder(
itemScrollController: _scrollController,
itemCount: _myList.length,
itemBuilder: (context, index) {
return _myList[index];
},
)
_scrollController.scrollTo(index: 150, duration: Duration(seconds: 1));
Code language: JavaScript (javascript)
Please note that the scrollable_positioned_list package is not officially supported by Google and may have performance issues with large lists.