Multiple listview.builder methods in single container - flutter

I have been trying to show few listviews in the same body container. I'm using Listview.builder because i have to fetch json data and display in a listview.
Each listview have to fetch data from different json files and display below the previous listview vertically(yes like in nested listview).
I have seen nested listvie examples but. Is it possible to do with listview.builder ? If so please show me example or a tutorial link. Thank You!
This is the code I'm use to create the listview.
ListView.builder(
itemCount: recent == null ? 0 : recent.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: <Widget>[
Card(
child: Column(
children: <Widget>[
new Image.network(recent[index]["_embedded"]["wp:featuredmedia"][0]["source_url"]),
new Padding(
padding: EdgeInsets.all(10.0),
child: new ListTile(
title: new Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: new Text(recent[index]["title"]["rendered"])),
subtitle: new Text(
recent[index]["excerpt"]["rendered"].replaceAll(new RegExp(r'<[^>]*>'), '')
),
),
)
],
),
)
],
);
},
)
);

You can achieve that by using SliverList with SliverChildBuilderDelegate:
CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
// First JSON
},
childCount: childCount,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
// Second JSON
},
childCount: childCount,
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
// Third JSON
},
childCount: childCount,
),
),
),
],
);

Related

multi type list View in Flutter

How I can display list View with multi-type for example(item 1: text, item 2: image with Text ...)
using flutter?
Here is the code:
I need to make the ListView show onlyText in item1, imageWithText for item2 and so on, How I can do that?
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(height: 5),
ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) => onlyText(),
separatorBuilder: (context, index) => SizedBox(height: 10),
itemCount: 100,
),
],
),
);
}
}
Widget imageWithText() => Container(
child: Card(
child: Row(
children: [
Text(
'sara ahmad',
style: TextStyle(fontSize: 16),
),
SizedBox(width: 10),
Image.network(
'https://th.bing.com/th/id/R.e3a5da5209f4c39f1899456c94371a6f?rik=mz9sVBWxRJKGgA&riu=http%3a%2f%2fmedia1.santabanta.com%2ffull1%2fAnimals%2fHorses%2fhorses-62a.jpg&ehk=o%2fS9l8DSJtUbl%2bYcrwLMJy6W4MfUby7bTUHRwJu7a%2bU%3d&risl=&pid=ImgRaw&r=0',
width: 100,
height: 100,
),
],
),
),
);
Widget onlyText() => Container(
child: Card(
child: Row(
children: [
Text(
'sara ahmad',
style: TextStyle(fontSize: 16),
),
SizedBox(width: 10),
Text('Nour'),
],
),
),
);
In the itemBuilder you can check if the item is only text or image with text with a ternary operator ?:, i.e. condition ? expr1 : expr2, like so:
itemBuilder: (context, index) => index == 0 ? onlyText() : imageWithText(),
Or, if you have a list of more than 2 items it could be something like this (assuming the items have a property bool isOnlyText):
itemBuilder: (context, index) => _chats[index].isOnlyText
? onlyText()
: imageWithText(),
Below is the result of the 1st snippet above:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
SizedBox(height: 5),
Expanded(
child: ListView.separated(
shrinkWrap: true,
itemBuilder: (context, index) =>
index == 0 ? onlyText() : imageWithText(),
separatorBuilder: (context, index) => SizedBox(height: 10),
itemCount: 100,
),
),
],
),
);
}
///crete an empty widget list
List<Widget> item_list=[];
///create a function to add data to list and call this function in the initstate
add_items_to_list()async{
item_list.add(Text(('data')));
item_list.add(Image.asset('name'));
///add as much as you want
}
///use widget as below
Widget items()=>ListView(
children: item_list,
);
if you want to show static list, you can do like this
itemBuilder: (context, index) => index.isEven
? onlyText()
: imageWithText(),
or you have dynamic data then follow below
let's assume you have list of Model class like this
class Model{
String text,
String img,
}
var list = <Model>[]; //your data will be here
and to check if is there only image, you need condition like below,
so in your ListView you can check like this
itemBuilder: (context, index) => list[index].img == null
? onlyText()
: imageWithText(),

Flutter - How to list out forEach() value in ListView builder?

Hi I am trying to list data from JSON to Listview Builder . But Flutter is giving me this error: Column's children must not contain any null values, but a null value was found at index 0
I tried to map each one like this inside the listview
alo[Index]['rewards'].forEach((k, v) {
Text(v['name']);
}),
Here is my full code:
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards'].forEach((k, v) {
Text(v['name']);
}),
],
),
));
});
Is there any solution to this? Thank you!
The thing is forEach() doesn't return anything, you could use map() instead, like this:
children: alo[Index]['rewards'].values.map<Widget>((v) => Text(v['name'])).toList()
If you want to add more widgets, you could do something like this:
Column(
children: <Widget>[
Column(
children: alo[Index]['rewards']
.values
.map<Widget>((v) => Text(v['name']))
.toList(),
),
Text('Other widget'),
],
)
You have two options, if you don't have any rewards then you can
a) Leave an empty card
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards']!=null?
alo[Index]['rewards'].forEach((k, v) {
return Text(v['name']);
}):SizedBox()
],
),
));
});
or
b) don't render any card
shrinkWrap: true,
itemCount: alo.length,
itemBuilder: (BuildContext ctxt, int Index) {
return alo[Index]['rewards']!=null?Card(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Column(
children: <Widget>[
alo[Index]['rewards'].forEach((k, v) {
return Text(v['name']);
}),
],
),
)):SizedBox();
});

Separator/Divider in SliverList flutter

How can we implement Separator/Divider in SliverList. ListView.separated is handy way to create separators in list but i do not see any docs or examples about SliverList
Similar as ListView.separated
import 'dart:math' as math;
List<String> values = List();
for (int i = 1; i <= 50; i++) {
values.add(i.toString());
}
return CustomScrollView(
semanticChildCount: values.length,
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
final int itemIndex = index ~/ 2;
if (index.isEven) {
return Padding(
child: Text(values[itemIndex]),
padding: EdgeInsets.all(16));
}
return Divider(height: 0, color: Colors.grey);
},
semanticIndexCallback: (Widget widget, int localIndex) {
if (localIndex.isEven) {
return localIndex ~/ 2;
}
return null;
},
childCount: math.max(0, values.length * 2 - 1),
),
),
],
);
Simple ways,
Using SliverFillRemaining
return CustomScrollView(
slivers: <Widget>[
SliverFillRemaining(
child: ListView.separated(
itemCount:value.length,
//shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
//padding: EdgeInsets.all(0),
separatorBuilder: (BuildContext context, int index){
return Divider();
},
itemBuilder: (BuildContext context, int index) {
//widget return
})
),
Using SliverList
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Column(
children: <Widget>[
SizedBox(height: 5),
//your main widget is here
SizedBox(height: 5),
Divider(height: 1)
],
);
},
childCount: model.length,
),
)
Although this question is very old, I will add my answer for future readers.
You simply wrap your widget with a Container and then you give the container a bottom border. Here is an example:
Container(
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey.shade300, width: 0.5))),
child: YourWidget(),
),
If you are wondering how to show Divider but not show on the last item. Try this.
Wrap your widget into Column then give a conditional for building Divider. The Divider Widget will show except on the last index. Example:
CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(_, int index) {
return Column(
children: <Widget>[
// Put your widget here
YourWidget(),
// This divider will not appears on last index
if(index != (item.length - 1))
const Divider(),
],
);
},
childCount: item.length,
),
),
],
),
You can use the Divider() Widget.
Here you can find the documentation.

how to change body text ontap of a listview.builder item while im using map<>

I want to know how can i make items in a list view builder clickable so i can change text in the body (outside list view builder) because I am using a map<> data
ListView.builder(
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
String key = values.keys.elementAt(index);
return new Column(
children: <Widget>[
new ListTile(
title: new Text("$key"),
subtitle: new Text("${values[key]}"),
),
new Divider(
height: 2.0,
),
],
);
},
);
new Text("${values[key]}"), i want to use this on body and change the text when i click on specific item .. thanks
You can use a variable to keep track on changes
1* declare variable
var myVar = "";
2* Edit your code
ListView.builder(
itemCount: values.length,
itemBuilder: (BuildContext context, int index) {
String key = values.keys.elementAt(index);
return new GestureDetector(
onTap: (){
setState((){myVar = values[key]});},
child: Column(
children: <Widget>[
new ListTile(
title: new Text("$key"),
subtitle: new Text("${values[key]}"),
),
new Divider(
height: 2.0,
),
],
));
},
);
3* Then on body you can use it like this
Text(myVar)

How to use divideTiles() in Flutter?

I am trying to build a ListView with dividers between each ListTile.
I saw that there is a static method to do that called divideTiles() but i did not understand how to use that.. How/where is this function used?
My code is a simple ListView with ListTiles as children.
ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
// your widgets here
]
).toList(),
)
Alternatively you can go with ListView.separated:
ListView.separated(
itemCount: 42,
itemBuilder: (context, index) {
// your widget here
},
separatorBuilder: (context, index) {
return Divider();
},
);
Here is a supplemental answer that shows what the divider looks like:
ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
ListTile(
title: Text('Horse'),
),
ListTile(
title: Text('Cow'),
),
ListTile(
title: Text('Camel'),
),
ListTile(
title: Text('Sheep'),
),
ListTile(
title: Text('Goat'),
),
]
).toList(),
)
From here
If you are using listview you can go with this alternate
ListView.builder(itemBuilder: (context, index){
return ListTile(title: new Column(children: <Widget>[
new Text('Hello how are you?'),
new Divider(height: 20.0,)// add value for height or leave it blank for default
],) );
})