Flutter: Scrolling to a desired Item in a ListView

Last updated on January 7, 2021 A Goodman Loading... Post a comment
This is the demo for the second example

This article shows you some different ways to programmatically scroll to a desired item in a ListView, for instance, scrolling to the item with the index of N when the user presses a floating button. Each approach mentioned in this tutorial comes along with a complete example to make it easier to understand. Without any further ado, let’s have a look at the first one.

Using ScrollController

If your ListView has items of the same height then this approach works just fine (fortunately, ListView generally contains a bunch of same-type and same-height children). In case the heights of the items are different and not set, move on to another method in this article.

Example

This example app contains a ListView with 100 items and a floating button. When the user presses the floating button, the view will scroll to a random item (you can replace it with a constant number if you want to). This item will also be highlighted with an orange background.

Preview:

The full code:

import 'package:flutter/material.dart';
import 'dart:math';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _scrollController = ScrollController();

  // Generate dummy data to fill the ListView
  final List<String> listItems = List.generate(100, (i) => "Item $i");

  // Define the fixed height for an item
  final double _height = 80;

  // Define the function that scroll to an item
  void _scrollToIndex(index) {
    _scrollController.animateTo(_height * index,
        duration: Duration(seconds: 2), curve: Curves.easeIn);
  }

  // The index of the destination item
  // It is a random number
  int _destinationIndex;

  // This is ued for creating a random number
  final _random = Random();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
      ),
      body: ListView.builder(
          controller: _scrollController,
          itemCount: listItems.length,
          itemBuilder: (_, index) {
            return Container(
                height: _height,
                child: Card(
                    color: index == _destinationIndex
                        ? Colors.orange
                        : Colors.blue[100],
                    child: Center(
                        child: Text(
                      listItems[index],
                      style: TextStyle(fontSize: 18),
                    ))));
          }),
      floatingActionButton: FloatingActionButton(
          onPressed: () {
            setState(() {
              _destinationIndex = _random.nextInt(100);
            });
            _scrollToIndex(_destinationIndex);
          },
          child: Icon(Icons.refresh)),
    );
  }
}

Using scrollable_positioned_list plugin

This plugin is published on pub.dev by google.dev. It gives us a widget named ScrollablePositionedList that not only provides features like ListView.builder but also supports stuff called scrollToIndex. Now the heights of the list items can be anything.

Example

Preview

Our app has a floating button and a list of 100 items of different heights. When the user presses the button, the view will scroll to the item which has an index of 50 (you can replace 50 by any integer between 0 and 100).

The full code:

import 'package:flutter/material.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'dart:math';

const totalItems = 100;

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final random = Random();

  // Generate dummy data
  final List<String> _myList = List.generate(totalItems, (i) => "Item $i");

  final ItemScrollController _itemScrollController = ItemScrollController();

  // This function will be triggered when the user presses the floating button
  void _scrollToIndex(int index) {
    _itemScrollController.scrollTo(
        index: index,
        duration: Duration(seconds: 2),
        curve: Curves.easeInOutCubic);
  }

  // The view will scroll to the item which has the index of 50
  // You can specify another number if you like
  final _desiredItemIndex = 50;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kindacode.com'),
      ),
      body: ScrollablePositionedList.builder(
        itemScrollController: _itemScrollController,
        itemCount: _myList.length,
        itemBuilder: (context, index) {
          return Card(
            margin: EdgeInsets.all(20),
            elevation: 10,
            child: Container(
              // give each container a random height
              height: random.nextDouble() * 150 + 50,
              color: _desiredItemIndex == index ? Colors.purple : Colors.amber,
              alignment: Alignment.center,
              child: Text(
                _myList[index],
                style: TextStyle(fontSize: 24),
              ),
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
          onPressed: () => _scrollToIndex(_desiredItemIndex),
          child: Icon(Icons.arrow_downward)),
    );
  }
}

Wrap Up

In this article, we have explored more than one approach to scroll to a specific item in a ListView or an alternative to ListView called ScrollablePositionedList. Depending on the needs and the situation that you are dealing with, choose an appropriate method from them.

If you would like to learn more about Flutter, take a look at the following articles: Flutter SliverList – Tutorial and Example, Using Stack and IndexedStack in Flutter, Working with dynamic Checkboxes in Flutter, Flutter AnimationController examples, or check out our Flutter category page and Dart category page for the latest stuff.

Related Articles

guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x