Jak wyświetlić przewijany indeks dla scrollController we flutter?
Chciałbym wyświetlić indeks na dole listView, używając scrollController, w taki sam sposób, w jaki jest wyświetlany na poniższym obrazku:
Po przewinięciu przez użytkownika w dół lub w górę, licznik po lewej stronie, podświetlony na czerwono, jest zwiększany / zmniejszany w zależności od kierunku przewijania użytkownika.
Chcę osiągnąć automatyczną aktualizację indeksu wyświetlanej pozycji, oznaczonego na obrazku czerwonym kolorem. Tak więc za każdym razem, gdy użytkownik przewinie w dół lub w górę, indeks ten jest aktualizowany o indeks wyświetlanego elementu.
Zdjęcie pokazuje, że osiągnąłem 26 pozycję. Za każdym razem, gdy przewijam w dół lub w górę, ten indeks jest aktualizowany.
Próbowałem użyć offsetu, który jest emitowany dla zdarzenia przewijania, bez powodzenia.
Odpowiedzi
Sposób polega na użyciu kontrolera przewijania, tak jak robiłeś.
Musisz użyć znanego rozmiaru elementu i nasłuchiwania.
// 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;
});
}
Dodanie detektora do scrollController wywoła wywołanie zwrotne podane za każdym razem, gdy lista jest przewijana. Możesz obsłużyć wiele zachowań listy, używając tej samej logiki, w tym identyfikować typ zdarzenia, które wywołało nasłuchiwanie, kierunek przewijania itp.
Istnieje biblioteka o nazwie scroll to index, która może Ci pomóc. Możesz wziąć indeks $ index, aby pokazać go w tostowej wiadomości. Poniższy przykład pochodzi od autora biblioteki:
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-d13d3c20d68bMoże ten może ci pomóc. Dostępny jest również kod źródłowy. Pomocna może być prosta matematyka dotycząca wysokości przedmiotu.