Separator/Divider in SliverList flutter - 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.

Related

Flutter List view builder doesn't shrink when Keyboard appears

I'm creating a chat feature in flutter but noticed this behavior on IOS that doesnt shrink the list so you can see the last sent message. How can I have the listview builder shrink to show the last message when the keyboard appears?
Note: This issue doesn't happen on Android
Scaffold(
resizeToAvoidBottomInset: true,
body: Stack(
children: <Widget>[
StreamBuilder(
stream: _chats,
builder: (context, snapshot) {
if (!snapshot.hasData) return Container();
return snapshot.hasData
? GestureDetector(
onPanDown: (_) {
FocusScope.of(context).requestFocus(FocusNode());
},
child: ListView.builder(
shrinkWrap: true,
controller: _scrollController,
padding: EdgeInsets.only(top: 10, bottom: 100),
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
return MessageWidget(
tripId: widget.docId,
uid: snapshot.data.docs[index].data()["uid"],
messageId: snapshot.data.docs[index].id,
message: snapshot.data.docs[index].data()["message"],
sender: snapshot.data.docs[index].data()["senderName"],
sentByMe: widget.uid ==
snapshot.data.docs[index].data()["uid"],
mediaFileUrl:
snapshot.data.docs[index].data()["mediaFileUrl"],
);
}),
)
: Container();
},
);
]
)
)
I think you can try the 'reverse' property from the ListView.builder.
Tell me if this example didn't fit your needs, can you share us your code ? (I didn't see why you use a Stack and what could be the issue around that).
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: Stack(
children: <Widget>[
StreamBuilder<dynamic>(
builder: (context, dynamic snapshot) {
return GestureDetector(
onPanDown: (_) {
FocusScope.of(context).unfocus();
},
child: ListView.builder(
reverse: true,
shrinkWrap: true,
itemCount: 100,
padding: const EdgeInsets.only(top: 10, bottom: 10),
itemBuilder: (context, index) {
return ListTile(title: Text(index.toString()));
},
),
);
},
),
],
),
),
Container(
padding: const EdgeInsets.all(8),
color: Colors.black12,
child: const TextField(),
),
],
),
);
}
}

RenderFlex children have non-zero flex but incoming height constraints are unbounded: Nested ListView

I am trying to build a Nested listview but getting "RenderFlex children have non-zero flex but incoming height constraints are unbounded" error with below code.
Layers are like this...
Each item of a horizontal ListView has a Text widget and a ListView widget.
At the second level, each item of vertical ListView contains again a Text widget and a ListView.
At the third level, each item of the ListView contains a Text widget.
-Horizontal ListView
- Person's Name
- ListView
- Relation Name
- ListView
- Person's Name
Thanks in advance.
person.relations is a Map<String, List<Person>>
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Relationship Explorer"),
),
body: SafeArea(
child: BlocBuilder<RelationCubit, CubitState>(
bloc: _cubit,
builder: (_, state) {
if (state is RelationSuccessState) {
return ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (_, outerIndex) =>
_relationTreeView(context, outerIndex),
itemCount: _cubit.people.length,
);
} else {
return WaitWidget();
}
},
),
),
);
}
Widget _relationTreeView(BuildContext context, int outerIndex) {
var person = _cubit.people[outerIndex];
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(person.displayName ?? ''),
Expanded(
child: Container(
width: MediaQuery.of(context).size.width,
child: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: person.relations?.length,
itemBuilder: (_, index) {
var persons = person.relations?[index];
return Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(person.relations!.keys.elementAt(index)),
Expanded(
child: Container(
width: MediaQuery.of(context).size.width,
child: ListView.builder(
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemCount: persons.length,
itemBuilder: (_, index) {
var innerPerson = persons[index];
return Text(innerPerson.displayName ?? '');
},
),
),
)
],
);
},
),
),
),
],
);
}
Wrap the list view with a container and give a height.

Flutter Wrap ListView.builder Horizontal

Widget build(BuildContext context) {
return Container(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: data[1].store.length,
itemBuilder: (BuildContext context, int index) {
return Wrap(
children: [
Text(data[1].store[index].number.toString()),
],
);
},
),
);
}
I used ListView.builder, I want to wrap Horizontal & scroll Vertical,.
I spend a lot of time on this stack...
My data from local JSON, with Future Builder and return to ListView.builder...
please see attach..
Thanks All...
Replace your Container with the below code.
SingleChildScrollView(
child: Column(
children: [
Wrap(
children: List<Widget>.generate(
1000,
(int index) {
return Text(index.toString() + ' ');
},
),
)
],
)),

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();
});

Multiple listview.builder methods in single container

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,
),
),
),
],
);