Как проскролить до нужного виджета в ListView?

Чтобы прокрутить до определенного элемента в ListView на Flutter, можно использовать ScrollController. Вот пример того, как это можно сделать:

  1. Создайте ScrollController и прикрепите его к вашему ListView.
  2. Вызовите метод animateTo для прокрутки до нужной позиции.

Пример кода:

import 'package:flutter/material.dart';

class ScrollToListView extends StatefulWidget {
  @override
  _ScrollToListViewState createState() => _ScrollToListViewState();
}

class _ScrollToListViewState extends State<ScrollToListView> {
  final ScrollController _scrollController = ScrollController();

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  void _scrollToIndex(int index) {
    final double position = index * 100.0; // Здесь 100.0 — это высота одного элемента.
    _scrollController.animateTo(
      position,
      duration: Duration(seconds: 1),
      curve: Curves.easeInOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scroll to List Item'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              controller: _scrollController,
              itemCount: 50,
              itemBuilder: (context, index) {
                return Container(
                  height: 100.0,
                  color: index % 2 == 0 ? Colors.blue : Colors.green,
                  child: Center(
                    child: Text(
                      'Item $index',
                      style: TextStyle(fontSize: 24),
                    ),
                  ),
                );
              },
            ),
          ),
          ElevatedButton(
            onPressed: () => _scrollToIndex(20), // Пример прокрутки до 20-го элемента.
            child: Text('Scroll to 20th item'),
          ),
        ],
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: ScrollToListView()));

Объяснение:

  • Используем ScrollController для управления прокруткой.
  • Метод animateTo принимает позицию в пикселях, до которой нужно проскролить. Для определения позиции умножаем индекс на высоту элемента.
  • Также можно использовать jumpTo, если анимация не важна.

Если элементы в ListView имеют разную высоту, тогда для корректного скроллинга до определенного элемента можно использовать GlobalKey для каждого элемента списка и вычислять их положение в списке динамически. Вот пример того, как это можно сделать:

import 'package:flutter/material.dart';

class ScrollToDynamicHeightListView extends StatefulWidget {
  @override
  _ScrollToDynamicHeightListViewState createState() => _ScrollToDynamicHeightListViewState();
}

class _ScrollToDynamicHeightListViewState extends State<ScrollToDynamicHeightListView> {
  final ScrollController _scrollController = ScrollController();
  final List<GlobalKey> _keys = List.generate(50, (index) => GlobalKey());

  void _scrollToIndex(int index) {
    final keyContext = _keys[index].currentContext;
    if (keyContext != null) {
      Scrollable.ensureVisible(
        keyContext,
        duration: Duration(seconds: 1),
        curve: Curves.easeInOut,
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scroll to List Item with Dynamic Height'),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView.builder(
              controller: _scrollController,
              itemCount: 50,
              itemBuilder: (context, index) {
                return Container(
                  key: _keys[index],
                  height: (index % 2 == 0) ? 150.0 : 100.0, // Элементы разной высоты
                  color: index % 2 == 0 ? Colors.blue : Colors.green,
                  child: Center(
                    child: Text(
                      'Item $index',
                      style: TextStyle(fontSize: 24),
                    ),
                  ),
                );
              },
            ),
          ),
          ElevatedButton(
            onPressed: () => _scrollToIndex(20), // Пример прокрутки до 20-го элемента
            child: Text('Scroll to 20th item'),
          ),
        ],
      ),
    );
  }
}

void main() => runApp(MaterialApp(home: ScrollToDynamicHeightListView()));

Объяснение:

  • Каждому элементу списка присваивается уникальный GlobalKey, что позволяет получить его текущее положение на экране через currentContext.
  • Функция Scrollable.ensureVisible автоматически скроллит до выбранного элемента, независимо от его высоты.
  • Это решение особенно полезно, когда высота элементов списка динамична и не фиксирована.

Таким образом, можно прокручивать список с элементами разной высоты до нужного элемента без необходимости вычислять его позицию вручную.