¿Cómo mostrar el índice de desplazamiento para scrollController en flutter?

Aug 21 2020

Me gustaría mostrar el índice en la parte inferior de listView utilizando scrollController, de la misma manera que se muestra en la siguiente imagen:

Después de que el usuario se desplaza hacia abajo o hacia arriba, el recuento de la izquierda, resaltado en rojo, aumenta o disminuye según la dirección de desplazamiento del usuario.

Lo que quiero lograr es actualizar automáticamente el índice del elemento mostrado, indicado en rojo en la imagen. Entonces, cada vez que el usuario se desplaza hacia abajo o hacia arriba, este índice se actualiza mediante el índice del elemento mostrado.

La imagen muestra que he alcanzado el punto 26. Siempre que me desplazo hacia abajo o hacia arriba, este índice se actualiza.

Intenté usar el desplazamiento que se está emitiendo para el evento de desplazamiento sin suerte.

Respuestas

2 Rod Aug 21 2020 at 02:23

La forma es usar el controlador de desplazamiento como lo estaba haciendo.

Debe utilizar un tamaño de elemento conocido y un oyente.

// 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;
  });
}

Agregar un oyente a scrollController llamará a la devolución de llamada proporcionada cada vez que se desplaza por la lista. Puede manejar muchos comportamientos de la lista usando la misma lógica, incluida la identificación del tipo de evento que disparó al oyente, la dirección del desplazamiento, etc.

LouisBelmont Aug 21 2020 at 01:52

Hay una biblioteca llamada scroll to index que podría ayudarte. Puede tomar el índice $ para que se muestre dentro de su mensaje brindis. El siguiente ejemplo es del autor de la biblioteca:

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-d13d3c20d68bQuizás este pueda ayudarte. También está disponible el código fuente. Una simple matemática sobre la altura del artículo podría ayudar.