我想进行一次聊天,其中只显示最后30条消息,其余的被删除。在我的应用程序中,每秒钟都会有一条评论被添加到聊天中(这是列表视图中的一个列表),如果这个列表大于30个元素,我会删除最后一条消息。
聊天自动滚动到底部,除非我开始从列表中删除元素(当我打印列表时,评论仍然会添加到列表中,只是不会显示在屏幕上)。有人知道为什么吗?
下面是一个简单的应用程序,它与我描述的问题完全相同。
import 'dart:async';
import 'package:flutter/material.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Timer? timerComments;
final ScrollController scrollController = ScrollController();
List<Widget> chat = [
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
const Text("comment"),
];
@override
void initState() {
// every second the chat gets updated
timerComments = Timer.periodic(const Duration(seconds: 1), (Timer t) {
chat.add(const Text("comment"));
if (chat.length >= 30) chat.removeAt(0);
setState(() {});
scrollDown();
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
width: 300, height: 300,
child: ListView( // here is the chat
shrinkWrap: true,
controller: scrollController,
children: chat,
),
),
),
);
}
// scroll down animation
void scrollDown() {
scrollController.animateTo(
scrollController.position.maxScrollExtent,
duration: const Duration(milliseconds: 1000),
curve: Curves.fastOutSlowIn
);
}
}
附加问题:为什么我必须首先初始化列表视图,然后用10条注解填充它,这样它就可以开始滚动了?如果没有评论或评论较少,列表视图不会滚动:(
我尝试了几种不同的setState((){})方法,但都不起作用。
1条答案
按热度按时间xmakbtuz1#
您面临的问题与
scrollDown()
方法调用和setState()
方法调用的计时有关。从聊天列表中删除元素时,调用setState()
重建UI,这将从屏幕中删除删除的元素。但是,在完全重新生成UI之前调用scrollDown()
方法,这会导致滚动行为不正确。要修复此问题,可以在完全重建UI后调用
scrollDown()
方法。一种方法是使用WidgetsBinding类,它允许您注册一个回调,当应用程序准备好绘制框架时将调用该回调。以下是如何修改代码以使用WidgetsBinding:在这段代码中,
addPostFrameCallback()
方法注册了一个回调,在UI完全重建后调用该回调。回调是一个不带参数的VoidCallback
,因此您可以传入一个调用scrollDown()
的匿名函数。这确保了在UI完全重建后滚动行为是正确的。