Флаттер, как создать автопрокрутку представления списка?
Я пытаюсь сделать ListView, который автоматически прокручивается до самой новой точки данных. Я устал делать это, делая функцию _scrollToBottom, которая использует метод.jumpTo.
Но я получаю пустой экран в приложении, и 'child.parentData != null': is not true.
в консоли отладки.
Любые предложения о том, как я могу реализовать автоматическую прокрутку?
Вот соответствующие части моего текущего кода:
ScrollController _scrollController = ScrollController();
_scrollToBottom(){ _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: DataShareWidget.of(context).stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){ return Text(snapshot.error);}
if(snapshot.hasData){
_dataFormat(snapshot.data);
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
_scrollToBottom();
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
}
);
}
4 ответа
Решение
Вам нужно позвонить _scrollToBottom()
метод, как только список построен полностью.
Модификация - это ваш код (без StreamBuilder):
ScrollController _scrollController = ScrollController();;
_scrollToBottom() {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom());
return Scaffold(
body: ListView.builder(
itemCount: 50,
// itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
return ListTile(
title: Text('Yo Dummy Text $index'),
// title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
),
);
}
Вам нужно это сделать и работать отлично....
ScrollController _scrollController = ScrollController();
@override
Widget build(BuildContext context) {
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: Duration(milliseconds: 200), curve: Curves.easeOut);
return StreamBuilder(
stream: stream = Firestore.instance
.collection('your collaction')
.document('your document')
.snapshots(),
builder: (context, snapshot) {
return snapshot.hasData
? ListView.builder(
controller: _scrollController,
shrinkWrap: true,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
msgTile(snapshot.data.documents[index], user1),
)
: Text('Loading...');
},
);
}
В трепете3.7+
это можно легко сделать, используя следующий код.
class _HomePageState extends State<HomePage> {
ScrollController scrollController = ScrollController(); // Define scrollController
List<String> assets = [...] // String of images to be displayed in listview
@override
void initState() { // create animation in initState
Future.delayed(const Duration(seconds: 1), () {
scrollController.animateTo(scrollController.position.maxScrollExtent,
duration: Duration(seconds: asset.length * 10), curve: Curves.linear);
});
// If you want infinite scrolling use the following code
scrollController.addListener(() {
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
// Scroll has reached the end, reset the position to the beginning.
scrollController.jumpTo(scrollController.position.minScrollExtent);
}
});
super.initState();
}
@override
void dispose() {
scrollController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return Scaffold(
body: SizedBox(
width: size.width,
height: size.height,
child: ListView.builder(
controller: scrollController, // assign scrollController here
....
// display your images here
),
),
);
}
Проблема в вашем коде StreamBuilder. Если снимок не готов, вам нужно что-то вернуть. Попробуйте этот код:
ScrollController _scrollController = ScrollController();
_scrollToBottom(){ _scrollController.jumpTo(_scrollController.position.maxScrollExtent);
}
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: DataShareWidget.of(context).stream,
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){ return Text(snapshot.error);}
if(snapshot.hasData){
_dataFormat(snapshot.data);
return ListView.builder(
itemCount: _listViewData.length,
controller: _scrollController,
reverse: true,
shrinkWrap: true,
itemBuilder: (context, index) {
_scrollToBottom();
return ListTile(
title: AutoSizeText(_listViewData[index], maxLines: 2),
dense: true,
);
},
);
}
//Something waiting the snapshot
return CircularProgressIndicator();
}
);
}