Saya memiliki scrollable di ListView
mana jumlah item dapat berubah secara dinamis. Setiap kali item baru ditambahkan ke akhir daftar, saya ingin menggulir secara terprogram ListView
ke akhir. (misalnya, sesuatu seperti daftar pesan obrolan di mana pesan baru dapat ditambahkan di akhir)
Dugaan saya adalah bahwa saya perlu membuat ScrollController
di State
objek saya dan meneruskannya secara manual ke ListView
konstruktor, jadi saya nanti dapat memanggil animateTo()
/ jumpTo()
metode pada pengontrol. Namun, karena saya tidak dapat dengan mudah menentukan offset gulir maksimum, tampaknya tidak mungkin untuk hanya melakukan suatu scrollToEnd()
jenis operasi (sedangkan saya dapat dengan mudah meneruskan 0.0
untuk membuatnya menggulir ke posisi awal).
Adakah cara mudah untuk mencapai ini?
Menggunakan reverse: true
bukanlah solusi yang tepat bagi saya, karena saya ingin item disejajarkan di atas saat hanya ada sejumlah kecil item yang muat dalam ListView
viewport.
Gunakan
ScrollController.jumpTo()
atauScrollController.animateTo()
metode untuk mencapai ini.Contoh:
final _controller = ScrollController(); @override Widget build(BuildContext context) { // After 1 second, it takes you to the bottom of the ListView Timer( Duration(seconds: 1), () => _controller.jumpTo(_controller.position.maxScrollExtent), ); return ListView.builder( controller: _controller, itemCount: 50, itemBuilder: (_, __) => ListTile(title: Text('ListTile')), ); }
Jika Anda ingin pengguliran halus, alih-alih menggunakan
jumpTo
penggunaan di atas_controller.animateTo( _controller.position.maxScrollExtent, duration: Duration(seconds: 1), curve: Curves.fastOutSlowIn, );
sumber
listViewScrollController.animateTo(listViewScrollController.position.maxScrollExtent)
adalah cara paling sederhana.sumber
untuk mendapatkan hasil yang sempurna saya menggabungkan jawaban Colin Jackson dan CopsOnRoad sebagai berikut:
_scrollController.animateTo( _scrollController.position.maxScrollExtent, curve: Curves.easeOut, duration: const Duration(milliseconds: 500), );
sumber
Saya memiliki begitu banyak masalah saat mencoba menggunakan pengontrol gulir untuk pergi ke bagian bawah daftar sehingga saya menggunakan pendekatan lain.
Alih-alih membuat acara untuk mengirim daftar ke bawah, saya mengubah logika saya untuk menggunakan daftar terbalik.
Jadi, setiap kali saya punya item baru, saya cukup, buat di sisipkan di bagian atas daftar.
// add new message at the begin of the list list.insert(0, message); // ... // pull items from the database list = await bean.getAllReversed(); // basically a method that applies a descendent order // I remove the scroll controller new Flexible( child: new ListView.builder( reverse: true, key: new Key(model.count().toString()), itemCount: model.count(), itemBuilder: (context, i) => ChatItem.displayMessage(model.getItem(i)) ), ),
sumber
Jangan letakkan widgetBinding di initstate, Anda harus meletakkannya di metode yang mengambil data Anda dari database. misalnya seperti ini. Jika diletakkan di initstate,
scrollcontroller
tidak akan dilampirkan ke listview apa pun.Future<List<Message>> fetchMessage() async { var res = await Api().getData("message"); var body = json.decode(res.body); if (res.statusCode == 200) { List<Message> messages = []; var count=0; for (var u in body) { count++; Message message = Message.fromJson(u); messages.add(message); } WidgetsBinding.instance .addPostFrameCallback((_){ if (_scrollController.hasClients) { _scrollController.jumpTo(_scrollController.position.maxScrollExtent); } }); return messages; } else { throw Exception('Failed to load album'); } }
sumber
Anda bisa menggunakan ini di mana
0.09*height
tinggi baris dalam daftar dan_controller
didefinisikan seperti ini_controller = ScrollController();
(BuildContext context, int pos) { if(pos != 0) { _controller.animateTo(0.09 * height * (pos - 1), curve: Curves.easeInOut, duration: Duration(milliseconds: 1400)); } }
sumber