I’m trying to show two lists whose data is updated from firebase firestore using stream builder. One list contains all the tasks and another list contains tasks with a field value "taskStatus" of true. Everything works fine, I wanted to add the functionality that when there’s no data in the "completedTasks" list, the whole widget area should just become invisible by changing the state of the visible parameter in the visibility widget. Here’s the code for changing the visibility based on snapshot data from firebase:
Expanded(
child: StreamBuilder<List<Task>>(
stream: DatabaseService().getCompletedTasks(orderName),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading();
}
List<Task>? completedTasks = snapshot.data;
return Opacity(
opacity: snapshot.data!.isEmpty ? 0 : 1,
child: Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 20),
child: Text(
"Completed Tasks",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: ListView.separated(
separatorBuilder: (context, index) =>
const SizedBox(
height: 5,
),
itemCount: completedTasks!.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
secondaryBackground: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
key: UniqueKey(),
onDismissed: (direction) {
DatabaseService()
.deleteTask(completedTasks[index].id);
AwesomeNotifications().cancelSchedule(
completedTasks[index].id);
},
child: Item(
task: completedTasks[index],
),
);
},
),
),
),
],
),
);
}),
),
To make changes, I’ve to hot reload the app. So, how can I change it to update the visibility without hot reloading the app.
Complete Code for both lists:
body: Column(
children: [
Expanded(
child: StreamBuilder<List<Task>>(
stream: DatabaseService().getTasks(orderName),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading();
}
List<Task>? tasks = snapshot.data;
if (snapshot.data!.isEmpty) {
return StreamBuilder(
stream: DatabaseService().getUniqueIDs(),
builder: (context, snapshot) =>
Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 40),
child: Text(
"Tasks",
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 30),
child: Container(
alignment: Alignment.center,
child: const Text(
"Great! You don't have any remaining tasks.",
style: TextStyle(
fontSize: 20,
fontFamily: "Roboto",
color: Colors.black,
),
),
),
),
const SizedBox(
height: 40,
),
Image(
image:
const AssetImage('assets/images/tasks.png'),
height: MediaQuery
.of(context)
.size
.height * 0.3,
),
],
),
);
}
return Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 40),
child: Text(
"Tasks",
style: TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: ListView.separated(
separatorBuilder: (context, index) =>
const SizedBox(
height: 5,
),
itemCount: tasks!.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
secondaryBackground: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
key: UniqueKey(),
onDismissed: (direction) {
DatabaseService()
.deleteTask(tasks[index].id);
AwesomeNotifications()
.cancelSchedule(tasks[index].id);
},
child: Item(
task: tasks[index],
),
);
},
),
),
),
],
);
}),
),
Expanded(
child: StreamBuilder<List<Task>>(
stream: DatabaseService().getCompletedTasks(orderName),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Loading();
}
List<Task>? completedTasks = snapshot.data;
return snapshot.data!.isEmpty ? SizedBox.shrink() : Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 30, vertical: 20),
child: Text(
"Completed Tasks",
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.grey[700],
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: ListView.separated(
separatorBuilder: (context, index) =>
const SizedBox(
height: 5,
),
itemCount: completedTasks!.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
secondaryBackground: Container(
color: Colors.red,
child: const Align(
alignment: Alignment.centerRight,
child: Padding(
padding: EdgeInsets.all(15.0),
child: Icon(
Icons.delete,
color: Colors.white,
),
),
),
),
key: UniqueKey(),
onDismissed: (direction) {
DatabaseService()
.deleteTask(completedTasks[index].id);
AwesomeNotifications().cancelSchedule(
completedTasks[index].id);
},
child: Item(
task: completedTasks[index],
),
);
},
),
),
),
],);
}),
),
],
),
2
Answers
You don’t need another parameter for that, do this:
or If you want just make it invisible, try this:
No need to use empty
SizedBox()
when you want to hide or show a widget on a condition.Instead of
SizedBox()
useSizedBox.shrink()
, it’ll taking as min space as possible and more optimized than using emptySizedBox()