flutter - Flutter Stateful 小部件不会重建
问题描述
提前感谢您的帮助,我有一个基本上是 TODO 应用程序的应用程序,这里的问题是我有一个字符串类型的列表,用户将在其中放置他需要做的任务,这就是为什么我尝试做的是检查列表何时仍然为空,显示一个带有图像的列,如果用户添加一个项目,则列表不再为空,所以它显示列表而不是列,因为我做了一个方法中的简单 if buildscreen()
。问题:将新项目添加到我的列表后的小部件即使在调用 setState 后也不会再次重建addTask()
,因此它看不到列表是满的还是空的,它会继续显示带有图像的列。
这是代码
import 'package:flutter/material.dart';
import 'package:todo_app/custom_icons_icons.dart';
class Todo extends StatefulWidget {
@override
_TodoState createState() => _TodoState();
}
List<String> tasks = [];
var hour= DateTime.now().hour;
int listlength= tasks.length;
class _TodoState extends State<Todo> {
GlobalKey<AnimatedListState> globalKey= new GlobalKey<AnimatedListState>();
void addTask(String text){
print("Add task is built");
setState(() {
tasks.insert(0,text);
globalKey.currentState.insertItem(0);
});
}
void removeTask(int index){
setState(() {
globalKey.currentState.removeItem(index, (context,animation){
return SizedBox(width: 0, height: 0);
});
tasks.removeAt(index);
});
}
Widget promptRemove(int index){
showDialog(context: context,
builder: (BuildContext builder){
return AlertDialog(
title: Text("Do you want to mark ${tasks[index]} as done?"),
actions: [
FlatButton(onPressed:() {
removeTask(index);
Navigator.pop(context);
}
, child: Text("Mark as Done")),
FlatButton(onPressed:(){
Navigator.pop(context);
}, child: Text("Cancel"))
],
);
}
);
}
Widget buildItem(String text, int index){
return Dismissible(
key: Key("${text.hashCode}"),
onDismissed: (direction)=> removeTask(index),
direction: DismissDirection.startToEnd,
child: Card(
elevation: 4,
child: ListTile(
leading: Container(
margin: EdgeInsets.only(
top: 5
),
child: Container(
child: Icon(Icons.lightbulb, size: 30, color: Colors.blue,))),
title: Text(text),
subtitle: Text("Today"),
trailing: Icon(Icons.arrow_forward_ios_rounded, color: Colors.blue,),
),
),
);
}
Widget buildList(){
return AnimatedList(
key: globalKey,
initialItemCount: tasks.length,
itemBuilder: (BuildContext context, int index, animation){
return SlideTransition(
position: Tween<Offset>(
begin: const Offset(-1, 0),
end: Offset(0, 0),
).animate(CurvedAnimation(
parent: animation,
curve: Curves.bounceIn,
reverseCurve: Curves.bounceOut)),
child: buildItem(tasks[index], index));
}
);
}
Widget buildscreen(){
print("Screen is built");
if(tasks.isEmpty){
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: Image.asset("assets/images/3327598.jpg"),
),
Text("Add tasks and start beign producivity "),
SizedBox(height: 100,)
],
),
);
}else{
return buildList();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
centerTitle: true,
elevation: 0,
backgroundColor: Colors.transparent,
actions: [
((){
if(hour>6 && hour<18){
return Container(
margin: EdgeInsets.only(
right: 20
),
child: Icon(CustomIcons.cloud_sun, color: Colors.blue,size: 28,));
} else {
return Container(
margin: EdgeInsets.only(
right: 20
),
child: Icon(CustomIcons.cloud_moon, color: Colors.blue,size: 28,));
}
}())
],
leading: Container(
width: 10,
height: 10,
margin: EdgeInsets.only(
top: 10,
left: 10,
right: 10,
bottom: 10
),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadiusDirectional.circular(30)
),
child: Center(child: Text("${tasks.length}")),
),
title: Text("Todo App",style: TextStyle(color: Colors.blue),),
),
floatingActionButton: FloatingActionButton(
onPressed:(){
Navigator.of(context).push(
new MaterialPageRoute(builder: (BuildContext context){
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text("Add a task"),
),
body: TextField(
onSubmitted:(val){
addTask(val);
Navigator.of(context).pop();
},
),
);
})
);
},
child: Icon(Icons.add),
),
body: buildscreen()
);
}
}
解决方案
问题是您没有检查 globalKey.currentState 是否为空,然后在 AnimatedList 小部件中对新项目的介绍进行动画处理。只需在插入 globalKey.currentState.insertItem(0) 之前添加以下检查。
if (globalKey.currentState != null)
这将确保您不会在小部件重建时插入项目,并且您将等待状态可用。添加此行后,您的 addTask() 方法应如下所示:
void addTask(String text) {
print("Add task is built");
setState(() {
tasks.insert(0, text);
if (globalKey.currentState != null) globalKey.currentState.insertItem(0);
});
}
推荐阅读
- javascript - 从我的谷歌电子表格设置电子邮件系统。除了在正文中添加图像之外,我还有其他一切工作
- spring-boot - Spring Cloud Gateway 可以与非异步的微服务一起使用吗?
- c# - 更新数据库并使用数据表和数据适配器
- http - 密码重置 (Parse-server/Heroku) -> {"error":"unauthorized"}
- php - 即使条件为假,PHP Laravel save() 也会保存
- r - 根据 R 中的条件为数据框的单元格着色
- python-3.x - 定义一个函数来查找给定字符串中的唯一回文
- java - 尝试使用 Hibernate 进行查询时出错(在 id 列表中的位置)
- c# - .net 属性不会从 json 反序列化为 .net 对象
- php - Laravel 将变量或对象共享给 Admin 中的所有控制器