Como exibir o índice de rolagem para scrollController em flutter?
Eu gostaria de exibir o índice na parte inferior de listView utilizando o scrollController, da mesma forma que é exibido na imagem a seguir:
Depois que o usuário rola para baixo ou para cima, a contagem à esquerda, destacada em vermelho, aumenta / diminui com base na direção de rolagem do usuário.
O que desejo alcançar é atualizar automaticamente o índice do item exibido, indicado em vermelho na imagem. Portanto, sempre que o usuário rola para baixo ou para cima, esse índice é atualizado pelo índice do item exibido.
A imagem mostra que alcancei o 26º item. Sempre que rolar para baixo ou para cima, esse índice é atualizado.
Eu tentei usar o deslocamento que está sendo emitido para o evento de rolagem sem sorte.
Respostas
O jeito é usar o controlador de rolagem como você estava fazendo.
Você precisa usar um tamanho de item conhecido e um ouvinte.
// 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;
});
}
Adicionar um listener a um scrollController chamará o callback fornecido toda vez que a lista for rolada. Você pode lidar com muitos comportamentos da lista usando a mesma lógica, incluindo a identificação do tipo de evento que disparou o ouvinte, a direção da rolagem, etc.
Existe uma biblioteca chamada scroll to index que pode ajudá-lo. Você poderia levar o $ index para mostrar dentro de sua mensagem do sistema. O exemplo abaixo é do autor da 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),
);
}
https://medium.com/flutter-community/create-shop-list-with-flutter-d13d3c20d68bTalvez este possa te ajudar. Também o código-fonte está disponível. Uma matemática simples sobre a altura do item pode ajudar.