What widget should I use? - flutter

This is what I am doing now.
Main Page:
I would like to make it same like this picture.Example:
I have tried couple ways and widget to build it but couldn't figure it out. Also, I want to retrieve the data from the Firebase and show them as the content.
Code 1: https://pastebin.com/A0nK1riQ
Code 2: https://pastebin.com/i1T7gBNy
Widget build(BuildContext context) {
return Container(
child: StreamBuilder(
stream: _products.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasData) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot =
streamSnapshot.data!.docs[index];
return Container(
margin: const EdgeInsets.all(10),
child: ListTile(
title: Text(documentSnapshot['name']),
subtitle: Text(documentSnapshot['price'].toString()),
trailing: SizedBox(
width: 100,
),
),
);
});
}
return SizedBox.shrink();
}),
);
}

You may use GridView.builder
https://api.flutter.dev/flutter/widgets/GridView-class.html
and in gridview build use column

According to me, first you have to check which NavigationRail icon clicked then put the condition on it's GestureDetector like
// global variable
String itemClickedValue = "";
then set the value in it according to user click
itemClickedValue = "first";
then check the condition while fetching data like
if(itemClickedValue.compareTo("first") == 0){
// pass that documentId or api and then show in list
}

Related

how to use two future builder in one page in flutter

In my Flutter app, I need to display two lists that are coming from the database, but I am having trouble getting both lists to display on the same screen. I am using two FutureBuilder widgets, but the first list is displaying correctly while the second list is still loading.
Here is the code I am using:
var future1 = FutureBuilder<List<QuranTextModel>>(
future: database.getQuranText(),
builder: (context, snapshot) {
if(snapshot.hasData){
return ScrollablePositionedList.builder(
itemScrollController: scrollToIndex,
itemCount: snapshot.data!.length,
initialScrollIndex: widget.position,
itemBuilder: (context, index) {
// Build the list item widget here
});
}else{
return const Center(child: CircularProgressIndicator(),);
}
}
);
var future2 = FutureBuilder<List<UrduTextModel>>(
future: database.getUrduTranlation(),
builder: (context, snapshot) {
if(snapshot.hasData){
return ScrollablePositionedList.builder(
itemScrollController: scrollToIndex,
itemCount: snapshot.data!.length,
initialScrollIndex: widget.position,
itemBuilder: (context, index) {
// Build the list item widget here
});
}else{
return const Center(child: CircularProgressIndicator(),);
}
}
);
Column(
children: [
SizedBox(
height: 200,
child: future1,
),
SizedBox(
height: 200,
child: future2,
),
],
)
The first FutureBuilder is used to build a list of QuranTextModel objects, and the second FutureBuilder is used to build a list of UrduTextModel objects. I am using a Column widget to display both lists, with each list contained within a SizedBox widget to give it a fixed height.
The issue I am having is that only the first list is displaying correctly, while the second list is still loading. How can I get both lists to display on the same screen?
Thank you for any help you can provide!
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 200,
child: future1),
SizedBox(height: 200,child: future2,)
],
),
),
Try this.
also you have to check your future status before populate you can check that by using
if (snap.connectionState == ConnectionState.done) { your code. you can check does snpa has data in it. }
connection state has deferent states that can help you to make your UI more interactive

Flutter : How to show Progress indicator until the data is fetched from the server [duplicate]

This question already has answers here:
Flutter how to user setState()
(2 answers)
Closed 8 months ago.
I want to show a progress indicator until the required data is fetched from the server. Currently what I am doing is made a function getQuotes() that will fetch the data into a variable using setState(). And the Used the FutureBuilder where its future parameter is set to getQuotes(). But this approach gives me a non-ending CircularProgressIndicator. I don't why it is happening. Is ther any problem with the combination of FutureBuilder() and setState() ? Can Some one help ?
Here is my code,
Map<String, dynamic> userInfo = {};
Future<void> getQoutes() async {
var data = await FirebaseFirestore.instance.collection('user').doc(auth.currentUser!.uid).get();
setState(() {
userInfo = data.data() as Map<String, dynamic>;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Some Quotes',
),
backgroundColor: Colors.deepOrange,
),
body: FutureBuilder (
future: getQoutes(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.done:
if (snapshot.hasError) {
return Text('Error : ${snapshot.error}');
}
return SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: ListView.builder(
itemCount: 3,
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
return Card_fun(userInfo['quotes'][index]);
}
)
)
],
),
)
);
default:
return const CircularProgressIndicator();
}
}
),
);
}
Another solution would be to make your getQuotes() function returning a Future<String> instead of a Future<void> and then access the data via the snapshot instead of accessing the state.
The Flutter docs of the FutureBuilder Flutter Docs are also doing it that way in the demo. As long as you don't need the state of userInfo in other places this should be an acceptable solution and you could also remove userInfo as variable. If you want to maintain or manipulate it later you could try to put the setState({}) statement in the ConnectionState.done switch case within an if(snapshot.hasData){} block.

ListView.builder inside FutureBuilder widget returns null even if it's populated?

So I'm new to Flutter and I keep running into the same issue.
Future<List<DonationDTO>> getUsersAppointments() async {
List<DonationDTO> AppointmentRes = [];
AppointmentRes = (await _apiClient.getDonationsOfUser(widget.user.id, widget.accesstoken));
return AppointmentRes;
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.pink,
elevation: .0,
leading: BackButton(
onPressed: () => Navigator.pop(context),
color: Colors.white),
title: Text("text"),
),
body:SingleChildScrollView(
child: FutureBuilder<List<DonationDTO>>(
future: getUsersAppointments(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData || snapshot.hasError) {
return new Container(child:CircularProgressIndicator());
} else {
return Container(
child: ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
if (!snapshot.data[index].hasData || snapshot.data[index].hasError) {
return new Container(child:CircularProgressIndicator());
} else {
return Text('${snapshot.data[index].id}');}
}));
}
}
),
),
),
);
}
The problem with this widget is that while using the ListView I keep getting a null value error, more specifically when I try to get data from snapshot.data[index].
It also appears that when I display the content of snapshot.data I get this:
[Instance of 'DonationDTO', Instance of 'DonationDTO']
I don't know how to fix this, so any help would be appreciated. Thanks!
snapshot.data[index] points to a list item of DonationDTO type, which has no hasData and hasError properties. In itemBuilder it is safe to use snapshot.data[index] without checks.
Well, the other answer is correct for this case. If you want to solve this not only this time but for all future uses, you should declare your types and not use implicit dynamic that you end up with if you miss a declaration.
A FutureBuilder<List<DonationDTO>> does not receive just any type of AsyncSnapshot. It receives a AsyncSnapshot<List<DonationDTO>>. And from there on, your compiler got your back. .data is no longer of type dynamic where you have to guess (in this specific case you guesses wrong, which explains your problem) but of type List<DonationDTO> and you and your compiler can tell exactly what to do and what would be wrong.

How can i include navigation for a listview in flutter ,

enter image description here
I want each list item to have its own route .I have attached a screenshot. My list view is customized, each item has its own name
Your question doesn't explain much, but rather than listview use listview.builder and then you can return any widget and pass your route based on itemindex.
ListView.builder(
itemCount: 10, *//Number of items in your static or dynamic*
itemBuilder: (context, index) {
return YourNewCommonWidgetForEveryItem(index);
},
),
For example I've to navigate the first item to somewhere else
Widget YourNewCommonWidgetForEveryItem(int Index){
return GestureDetector(
onTap:()=> index==0 ? locationtofirstItem : defaullt,
child: yourDesign(),
),
}
OfCourse the Above method won't work if you don't know where to navigate which item.
body: new ListView(
padding: const EdgeInsets.all(20.0),
children: List.generate(choices.length, (index) {
return Center(
child: ChoiceCard(
choice: choices[index],
item: choices[index],
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Detail(choice: choices[index])),
);},),);}))

Flutter Firebase only let certain data be shown on list view builder

I am trying to only display certain data from a collection. In my example, I only want to show data in the list where the collection in name on firebase is equal to the name of the widget. I am unable to solve this problem
Expanded(
child: Container(
child: FutureBuilder(
future: getPosts(),
builder: (_,snapshot){
if(snapshot.data["name"]== widget.info.name){
return ListView.builder(
itemCount:
x,
itemBuilder: (_,index){
return ListTile(
title: Text(snapshot.data[index].data["name"]),
);
});
Expanded(
child: Container(
child: FutureBuilder(
future: getPosts(),
builder: (_,snapshot){
return ListView.builder(
itemCount:
snapshot.data,
itemBuilder: (_,index){
if(snapshot.data["name"]== widget.info.name){
return ListTile(
title:Text(snapshot.data[index].data["name"]),
);
}else{
return Container();
}
})}))
);
A better option will be to pass the widget name in the getPosts() function you defined and update the firebase query to do the filtering. This way it be much faster as firebase does the require indexing and will do the filtering in O(len(filtered_elements)) rather than current time complexity of O(len(all_elements)).