Как отобразить индекс прокрутки для scrollController во флаттере?

Aug 21 2020

Я хотел бы отобразить индекс в нижней части listView, используя scrollController, так же, как он отображается на следующем изображении:

После того, как пользователь прокручивает страницу вниз или вверх, счетчик слева, выделенный красным, увеличивается / уменьшается в зависимости от направления прокрутки пользователя.

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

На картинке видно, что я дошел до 26-го пункта. Когда я прокручиваю вниз или вверх, этот индекс обновляется.

Я безуспешно пытался использовать смещение, которое создается для события прокрутки.

Ответы

2 Rod Aug 21 2020 at 02:23

Способ заключается в использовании контроллера прокрутки, как и вы.

Вам нужно использовать известный размер элемента и слушателя.

// Declaring the controller and the item size
ScrollController _scrollController;
final itemSize = 100.0;

// Initializing
@override
void initState() {
  _scrollController = ScrollController();
  _scrollController.addListener(_scrollListener);
  super.initState();
}

// Your list widget (must not be nested lists)
ListView.builder(
      controller: _scrollController,
      itemCount: <Your list length>,
      itemExtent: itemSize,
      itemBuilder: (context, index) {
          return ListTile(<your items>);
      },
),

// With the listener and the itemSize, you can calculate which item
// is on screen using the provided callBack. Something like this:
void _scrollListener() {
  setState(() {
    var index = (_scrollController.offset / itemSize).round() + 1;
  });
}

Добавление слушателя к scrollController будет вызывать обратный вызов, предоставляемый каждый раз при прокрутке списка. Вы можете обрабатывать многие варианты поведения списка, используя ту же логику, включая определение типа события, вызвавшего запуск слушателя, направление прокрутки и т. Д.

LouisBelmont Aug 21 2020 at 01:52

Существует библиотека под названием scroll to index, которая может вам помочь. Вы можете взять индекс $, который будет отображаться внутри вашего тост-сообщения. Ниже приведен пример от автора библиотеки:

import 'dart:math' as math;

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Scroll To Index Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Scroll To Index Demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  static const maxCount = 100;
  final random = math.Random();
  final scrollDirection = Axis.vertical;

  AutoScrollController controller;
  List<List<int>> randomList;

  @override
  void initState() {
    super.initState();
    controller = AutoScrollController(
      viewportBoundaryGetter: () => Rect.fromLTRB(0, 0, 0, MediaQuery.of(context).padding.bottom),
      axis: scrollDirection
    );
    randomList = List.generate(maxCount, (index) => <int>[index, (1000 * random.nextDouble()).toInt()]);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        scrollDirection: scrollDirection,
        controller: controller,
        children: randomList.map<Widget>((data) {
          return Padding(
            padding: EdgeInsets.all(8),
            child: _getRow(data[0], math.max(data[1].toDouble(), 50.0)),
          );
        }).toList(),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _scrollToIndex,
        tooltip: 'Increment',
        child: Text(counter.toString()),
      ),
    );
  }

  int counter = -1;
  Future _scrollToIndex() async {
    setState(() {
      counter++;

      if (counter >= maxCount)
        counter = 0;
    });

    await controller.scrollToIndex(counter, preferPosition: AutoScrollPosition.begin);
    controller.highlight(counter);
  }

  Widget _getRow(int index, double height) {
    return _wrapScrollTag(
      index: index,
      child: Container(
        padding: EdgeInsets.all(8),
        alignment: Alignment.topCenter,
        height: height,
        decoration: BoxDecoration(
          border: Border.all(
            color: Colors.lightBlue,
            width: 4
          ),
          borderRadius: BorderRadius.circular(12)
        ),
        child: Text('index: $index, height: $height'),
      )
    );
  }

  Widget _wrapScrollTag({int index, Widget child})
  => AutoScrollTag(
    key: ValueKey(index),
    controller: controller,
    index: index,
    child: child,
    highlightColor: Colors.black.withOpacity(0.1),
  );
}
AlperenEkin Aug 21 2020 at 13:18

https://medium.com/flutter-community/create-shop-list-with-flutter-d13d3c20d68bМожет, это поможет тебе. Также доступен исходный код. Может помочь простая математика о высоте предмета.