When adding new items (e.g. a ListTile) to a ListView is there a way to scroll the newly added item into view? The new item may not be at the bottom of the list (e.g. it is sorted alphabetically).
All you have to do is set Global Keys for your widgets and call Scrollable. ensureVisible on the key of your widget you want to scroll to. For this to work your ListView should be a finite List of objects.
Listview so have inbuild scrolling capabilities. So you can not use listview inside scrollview. Encapsulate it in any other layout like LinearLayout or RelativeLayout.
A scroll controller creates a [ScrollPosition] to manage the state-specific to an individual [Scrollable] widget. To use a custom [ScrollPosition], subclass [ScrollController] and override [createScrollPosition]. A [ScrollController] is a [Listenable].
You can scroll through a ListView
using a ScrollController
.
final scrollController = ScrollController();
// ...
ListView(controller: scrollController // ...
);
// ...
scrollController.animateTo(height, duration: Duration(milliseconds: 678),
curve: Curves.ease);
You will have to determine the height yourself. That could be done using the index of your item and the general item height.
There is a full example available here.
You can use the following library from quire-io team to scroll ListView to the position:
https://github.com/quire-io/scroll-to-index
ListView(
scrollDirection: scrollDirection,
controller: controller,
children: randomList.map<Widget>((data) {
final index = data[0];
final height = data[1];
return AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: Text('index: $index, height: $height'),
highlightColor: Colors.black.withOpacity(0.1),
);
}).toList(),
)
Expanding on @creativecreatorormaybenot, if you want to do this after you have added an item, of course you need to prompt it to draw with a setstate, but there are some other critical pieces. For example, this code will automatically scroll so that the end of the list is visible just after it builds the list:
class MyList extends StatefulWidget {
@override
_MyState createState() => _MyState();
}
class _MyState extends State<MyList> {
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
}
void _onAfterBuild(BuildContext context) {
_scrollController.animateTo(double.maxFinite, /* <- the offset in units to scroll to */
duration: Duration(milliseconds: 1), curve: Curves.ease);
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => _onAfterBuild(context));
return ListView.builder(
controller: _scrollController,
//initialScrollIndex: appState.doseEvents?.length ?? 0,
itemCount: 20,
itemBuilder: (BuildContext ctxt, int index) {
return Row(
children: <Widget>[
Text("A"),
Text("B"),
Text("C"),
],
);
});
}
}
If you want to go to a particular item, you are going to have to compute the offset to that item in _onAfterBuild. For example:
void _onAfterBuild(BuildContext context) {
double scrollPos = _mostRecentlyAddedIndex * _itemHeight;
_scrollController.animateTo(scrollPos,
duration: Duration(milliseconds: 1), curve: Curves.ease);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With