заранее спасибо за вашу помощь, у меня есть приложение, которое в основном является приложением TODO, проблема здесь в том, что у меня есть список типа String, в котором пользователь будет помещать задачи, которые ему нужно выполнить, и именно поэтому я попытаться сделать, это проверить, когда список все еще пуст, показать столбец с изображением, и если пользователь добавляет элемент, список больше не пуст, поэтому он показывает список, а не столбец, для этого я сделал просто если в методе 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);
});
}
Вам нужно дождаться перестроения элемента, прежде чем вы сможете добавить его в globalKey.currentState.
Хорошо, я понял, у меня есть еще один вопрос, возможно ли, что это также произошло с моим приложением, я попытался создать горизонтальное представление списка, и оно работает отлично, но дочерний элемент этого представления списка занимает всю высоту представления списка, даже когда Я поставил термоусадочную пленку true, и даже когда дочерний контейнер имеет значение высоты.
Я должен буду увидеть код. Но я думаю, что если высота контейнера установлена, то он не должен расширяться, чтобы занять все доступное пространство. Если ListView у вас не работает, вы можете попробовать ScrollableRow. Я прошу вас поставить лайк / проголосовать за принятый ответ. Спасибо
Спасибо :) Я проверю ваше предложение
Спасибо, это решило мою проблему, но мне нужно больше понять, в чем была проблема, если вы можете объяснить это мне, я не понял, что вы пытаетесь мне сказать.