Flutter ListView.builder() is loading all items at once - flutter

I have a ListView I'm initializing with ListView.builder() and it seems to be loading all items at once. This is the code:
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
if (index == length) {
Future.delayed(Duration(seconds: 2)).then((value) {
setState(() => length += 10);
});
return Center(child: CircularProgressIndicator());
}
return Container(
color: Colors.red,
padding: EdgeInsets.all(24.0),
margin: EdgeInsets.all(12.0),
child: Text(index.toString()),
);
},
itemCount: length + 1,
)
This ListView is wrapped in another ListView. I'm trying to make a network call to load more items once I hit the bottom of the list, but it just gets called over and over again even when I haven't scrolled to the bottom. Is this because I have it nested in a second ListView?

Related

Flutter: Add padding to only certain elements in my ListView

I'm trying to create a ListView and would only want the first item to be padded. Here is the code:
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(16),
itemCount: card.length,
itemBuilder: (context, index) {
if (index == 0) {
return MyCard.buildRecordCard(
card[index], context);
} else {
return MyCard.buildRecordsCards(
card[index], context, index);
}
},
),
);
The output looks as follows:
but I want cards 2...n (i.e. index != 0) not to be padded and to stretch out to the end of the screen. Something like this:
if (index == 0) {
padding: EdgeInsets.all(16),
return MyCard.buildRecordCard(
card[index], context);
} else {
padding: 0,
return MyCard.buildRecordsCards(
card[index], context, index);
}
but that obviously doesn't work.
You just needed to wrap the widget with Padding.
simply you can use ternary like
itemBuilder: (context, index) {
return Padding(
padding: index == 0 ? EdgeInsets.all(16) : EdgeInsets.zero,
child: MyCard.buildRecordCard(card[index], context));
},
Solved.
I just added the padding to the item I was building by wrapping it in a container as follows:
Container(
padding: EdgeInsets.fromLTRB(16, 16, 16, 0),
child: ...ListTile...

flutter nested listview scroll animate to last item of child listview

I use two listview as nested for chats. Parent listview show date and child listview show chat messages. I try to scroll (jump or animate) last item of child listview automatically when send message. Like whatsapp. I do it scroll parent last item but ı can not also scrolling end of child listview. How can ı scroll programmatically to child listview last index item.
itemScrollController = ItemScrollController();
jump code
#observable
dynamic jumpToLastMessage() async {
print("parent index :${messages.length - 1}");
print("child index :${messages[messages.length - 1].messages!.length - 1}");
itemScrollController!.scrollTo(
index: messages.length - 1,
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
);
}
view code
ScrollablePositionedList.builder(
itemScrollController: viewModel.itemScrollController,
itemCount: viewModel.messages.length,
itemBuilder: (context, index) {
ChatMessage chatMessage = viewModel.messages[index];
return StickyHeader(
header: Center(
child: Container(
margin: EdgeInsets.only(top: 4),
padding:
EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration(
color: context.colors.surface,
borderRadius: BorderRadius.circular(20)),
child: Text(
'${chatMessage.date}',
style: TextStyle(
color: context.colors.onSurface,
fontSize: 12,
fontWeight: FontWeight.bold),
),
),
),
content: ListView.builder(
shrinkWrap: true,
// controller: viewModel.scrollController,
physics: NeverScrollableScrollPhysics(),
itemCount: chatMessage.messages!.length,
itemBuilder: (BuildContext context, int index2) {
if (index2 == chatMessage.messages!.length) {
return Container(height: 100);
}
return buildSingleMessage(
viewModel,
chatMessage.messages![index2],
context,
);
},
),
);
},
)

Flutter Listview.Separated add Separator at beginning and end of list

Using flutter, what is the easiest and cleanest way to place a separator not only between the rows, but also as the first and last row ?
I am able to do so by faking the itemCount and adding to extra rows.
...
child: ListView.separated(
// Offset itemCount to start with separator
itemCount: sortedList.length + 2,
itemBuilder: (context, index) {
if (index == 0) {
return SizedBox(height: 0.0);
}
if (index == sortedList.length + 1) {
return SizedBox(height: 0.0);
}
return ListItem(...);
},
separatorBuilder: (context, index) {
return SizedBox(height: 10.0);
}))),
I'm afraid this is as clean as we can get with ListView.separated
ListView.separated(
separatorBuilder: (context, index) => const Divider(height: 1.0,),
itemCount: 2 + boardList.length,
itemBuilder: (context, index) {
if (index == 0 || index == boardList.length + 1) return const SizedBox.shrink();
return MenuItem(
board: boardList[index - 1],
isSelected: boardList[index].id == selectedBoardId
);
},
);
Another way is to use ListView.builder and wrap your item a container with border bottom
ListView.builder(
itemCount: boardList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: (widget.isSelected) ? Colors.grey[50] : color,
border: Border(
top: (index == 0) ? BorderSide(color: Theme.of(context).dividerColor) : BorderSide.none
bottom: BorderSide(color: Theme.of(context).dividerColor)
)
)
),
},
);
You can wrap your ListView.serarated in another ListView and then put your Dividers before and after the ListView.separated. But you need to define the scrollDirection and shrinkWrap as shown in the example. Otherwise, you will get an error for unbounded hight. As separators, I used the Divider-Widget but you can use whatever you want.
ListView(
children: <Widget>[
Divider(),
ListView.separated(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: // ...
separatorBuilder: // ...
itemCount: // ...
),
Divider(),
],
),

How to populate custom widget items into listview in flutter?

I want to create listview like this image. How can I achieve this using flutter?
Please do a favour if you know how to make it?
You need a List view widget and with builder which contains a card widget which has Row as child.
ListView :-
ListView.builder(
padding: EdgeInsets.all(10.0),
shrinkWrap: false,
itemCount: model.length,
itemBuilder: (BuildContext context, int index) {
return listItem(context, index);
},
List item :-
model is removed
Widget listItem(BuildContext context, int index) {
return Card(
child: Row(
children: <Widget>[
Container(margin: EdgeInsets.all(10),child: Text("1")),
Container(height: 20,width: 1,color: Colors.blue,),
Container(margin:EdgeInsets.all(10),child: Text("asdasd"))
],
),
);
}

Card not clickable in a Stack

I am following https://github.com/devefy/Flutter-Story-App-UI to build some UI components but I can't seem to make the cards clickable.
The PageView builder is supposed to manipulate the currentPage value to change the page, but the PageView builder is on top of the stack and blocks all GestureDetectors under it.
I can't think of any solutions atm, any help is appreciated.
PageController cardController =
PageController(initialPage: images.length - 1);
cardController.addListener(() {
setState(() {
currentPage = cardController.page;
});
});
Stack(
children: <Widget>[
StackedCards(currentPage,postList),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: cardController,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
)
],
)
Some clickable widgets : GestureDetector, InkWell, InkResponse
GestureDetector(
onTap: ...,
child: Stack(
children: <Widget>[
StackedCards(currentPage,postList),
Positioned.fill(
child: PageView.builder(
itemCount: images.length,
controller: cardController,
reverse: true,
itemBuilder: (context, index) {
return Container();
},
),
)
],
));