What I want to do is to add an extra LisTile to the last of ListView but I still don't figure it out.
My current code is like this.
child: ListView.builder(
itemBuilder: (context, index) {
if (index == 0) {
// Add an extra item to the start
return ListTile(
...
);
}
index -= 1;
final item = _items[index];
// I want to an extra item here as well
if (index == _items.length) {
return ListTile();
}
return ListTile(
...
);
},
itemCount: _items.length + 2,
I've already tried the way above, but it doesn't work. There is an error.
Invalid value: not in range 0..4, inclusive 5
When I changed itemCount to _items.length + 1, it doesn't show the extra ListTile I want to add to the end.
If you want to add to the beginning and the end as well check below
child: ListView.builder(
itemBuilder: (context, index) {
if (index == 0) {
// Add an extra item to the start
return ListTile(
...
);
}
if (index == _items.length + 1) {
return ListTile();
}
index -= 1;
final item = _items[index];
return ListTile(
...
);
},
itemCount: _items.length + 2,
your bug is here:
itemCount: _items.length + 2,
you should increase it by one
because you added 2 elements and for the last call you get index = list.length + 1, and then you subtract 1 from it, and you end up 1 over your length.
ex lets say your list have 5 elements, because you have
itemCount: _items.length + 2
Listview will call your func 7 times, and in 7th call your index is 6 and you are doing index =-1, which equals to 5, and 5 is over your range. (you have form 0 to 4)
Related
I am trying to place an advertisement after every 3rd index. I got the required output but my problem in my case is i have a two type of List,
List One has 50 datas in it.
List two has only 5 datas.
When i tried with the below code.
ListView.separated(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(15),
shrinkWrap: true,
itemCount: articles.length,
separatorBuilder: (context, index) => SizedBox(
height: 15,
),
itemBuilder: (BuildContext context, int index) {
final Article article = articles[index];
final Sponsor sponsor = sponsors[index];
if(index %3 == 0 && index != 0) return SponsorCard(sponsor: sponsor, scaffoldKey: widget.scaffoldKey);
return Card4(article: article, heroTag: 'recent${article.id}', scaffoldKey: widget.scaffoldKey);
widget.scaffoldKey);
},
),
i am getting range error since sponsor list reached its last position.
error
The following RangeError was thrown building:
RangeError (index): Invalid value: Not in inclusive range 0..4: 49
What i need is that i need to make the sponsor list as loop so that if the List reached its last position it has to move again to the first position.
Can someone please help me on this.
You can create a new combined list as,
and make sure both Article & Sponsor class should be child class of ListItem.
OR
you need to wrap Article & Sponsor classes under ListItem Wrapper class
List items = []
Now use the items with ListView :
ListView.separated(
physics: NeverScrollableScrollPhysics(),
padding: EdgeInsets.all(15),
shrinkWrap: true,
itemCount: items.length,
separatorBuilder: (context, index) => SizedBox(
height: 15,
),
itemBuilder: (BuildContext context, int index) {
if (item[index] is Articles){
return SponsorCard(..);
}else{
return Card4(...);
}
},
);
Added Example on Request comment:
class _ListItem {
final bool isArticleType;
final dynamic value;
_ListItem(this.isArticleType, this.value);
}
class Article {}
class Sponsor {}
List<_ListItem> createList(List<Article> articles, List<Sponsor> sponsors) {
List<_ListItem> items = [];
items.addAll(articles.map((e) => _ListItem(true, e)).toList());
var index = 0;
var sIndex = 0;
for (var i = 0; i < articles.length && sIndex < sponsors.length; i++) {
if (i != 0 && i % 3 == 0) {
items.insert(index, _ListItem(false, sponsors[sIndex]));
sIndex++;
index++;
}
index++;
}
return items;
}
Thanks for your response guys.
I could achieve by the below code.
itemBuilder: (BuildContext context, int index) {
actualIndex = actualIndex +1;
if(sponsorIndex+1 >= sponsors.length){
sponsorIndex = -1;
}
if(index == 0 ){
articleIndex = -1;
}
if ((actualIndex-tempIndex) % 3 == 0 && actualIndex != 0 && (actualIndex-prevIndex) >=3 ) {
tempIndex = tempIndex +1;
prevIndex = actualIndex;
sponsorIndex = sponsorIndex + 1;
final Sponsor sponsor = sponsors[sponsorIndex];
return SponsorCard(sponsor: sponsor, scaffoldKey: widget.scaffoldKey);
}
articleIndex = articleIndex + 1;
final Article article = articles[articleIndex];
return Card4(article: article, heroTag: 'recent${article.id}', scaffoldKey: widget.scaffoldKey);
},
// Build the whole list of todo items
Widget _buildTodoList() {
return new ListView.builder(
itemBuilder: (context, index) {
// itemBuilder will be automatically be called as many times as it takes for the
// list to fill up its available space, which is most likely more than the
// number of todo items we have. So, we need to check the index is OK.
if (index < _todoItems.length) {
return _buildTodoItem(_todoItems[index], index);
}
},
);
}
Attempting to run a simple widget inside my program but receive the
"body_might_complete_normally" error.
How can I correct this?
itemBuilder only return on (index < _todoItems.length), you need to make sure return widget on every case.
Widget _buildTodoList() {
return ListView.builder(
itemCount:_todoItems.length, // your list length
itemBuilder: (context, index) {
if (index < _todoItems.length) {
return _buildTodoItem(_todoItems[index], index);
}
return Text("default case");// if above condtions dont meet, return this
},
);
}
Can you please tell me if it is possible to create a ListView but always have 1 fixed item at the end of the list, thus allowing a new card to be added. As shown in the screenshot below. There is a regular list of cards and at the end a card with an Add New Point button, when clicked, an action occurs (adding a new element to the end of the list).
If you know how to implement such an element as Add New Poynt, please tell me, I will be grateful.
Very simple, use [...oldList] to create a new List and add your fixed item after it like [...oldList, fixedItem].
Example:
Example with ListView:
You can increase itemLength by 1 and while check if the index is last one, provide your fixed widget.
ListView.builder(
itemCount: itemLength + 1,
itemBuilder: (context, index) {
if (index == itemLength) {
return Text("last Item");
}
return Text("item $index");
},
),
This is only logic please try it your own widget. Because I have not laptop.
**This code has syntax error please chaeck it because i have not laptop **
int howManyWidgetDraw = 5;
ListView.builder(
itemCount: howManyWidgetDraw,
itemBuilder: (BuildContext context,int
index){
if(howManyWidgetDraw==index.length){
return InkWell(
onTap(){
howManyWidgetDraw=howManyWidgetDraw+1;
//Call setstate method.
},
child: Text("last element print"));
}
else{
return Text("first four element");
}
}
),
);
Have any issue please ask me?
Try to use ListView.separated:
ListView.separated(
itemCount: _myList.length,
itemBuilder: (context, index){
return /* Your list item widget here */;
},
separatorBuilder: (context, index){
if(index == _myList.length-1) {return Text('Add New Poynt');}
else {return SizedBox();}
}
),
I have several data in my listview and i want to check if any of the data satisfies this if condition, let it stay at the top of the listview at 0 index.
ListView.builder(
itemCount: boolS == true ? 7 : data.length,
itemBuilder: (ctx, idx) {
if (boolS == true) {
return shimmer();
}
var index = data[idx];
if (index.userId == userId) {
// make the data stay at the top
}
return Container(
///....
);
),
Please how do i achieve this. I tried adding this to the listview
itemCount: boolS == true ? 7 : data.length + 1,
///...
if(idx == 0 && index.userId == userId) {
return Container();
}
but i don't think that's gonna work. So please can you guys help me out. Thanks
if (index.userId == userId) {
// make the data stay at the top
data.insert(0, index);
data.removeAt(idx+1);
}
Hi there please help me how to push item from list to grid, i have implement this https://flutter.dev/docs/cookbook/lists/mixed-list , what i want is how to push every 6 MessageItem to grid with two columns. thanks.
here my sample code:
ListView.builder(
controller: _controller,
itemCount: widget.ditems.length,
itemBuilder: (context, index) {
final item = widget.ditems[index];
if (item is HeadingItem) {
return TabHomeHeaderUi();
} else if (item is HeadlineItem) {
return TabHomeHeadline();
} else if (item is PopularItem) {
return TabHomePopular();
} else if (item is MessageItem) {
return
//here return 6 item
ListTile(
title: Text(item.sender),
subtitle: Text(item.body),
);
}
},
),