RangeError (index): Invalid value: Not in range 0..1, inclusive: 2. How can this be fixed? - flutter

I am building a static ListView. How can I solve this error? Also how can I add a UI to the ListView?
Following is my class MatchData code:
class MatchData {
String date, team1, team2, time;
MatchData({#required this.date, #required this.team1, #required this.team2, #required this.time});
}
Following is the Data I want to show in the ListView:
final List<MatchData> dayMatch = [
MatchData(
date: '12/02/2020',
team1: 'Mumbai Indians',
team2: 'Bangalore',
time: '16:00'),
MatchData(
date: '12/02/2020',
team1: 'Mumbai Indians',
team2: 'Bangalore',
time: '16:00')
];
match() {
return dayMatch;
}
Following is the body of my Widget:
body: Center(child: ListView.builder(itemBuilder: (context, index) {
return Card(
child: Row(
children: <Widget>[
Text(dayMatch[index].date),
Text(dayMatch[index].team1),
Text(dayMatch[index].time),
Text(dayMatch[index].team2),
],
),
);
}

If you don't specify itemCount and the screen is big enough to display ten items, ListView.builder() builds a little more than ten children, and even more on demand if you scroll down.
In your case, ListView.builder() tries to build more than two children, while your list (dayMatch) only has two elements, which is why the error occurs.
To fix it, just pass the number of items to the itemCount argument, or it'll be somewhat better to use the default constructor of ListView instead if the number is fixed and small. ListView.builder() does more computing under the hood to be flexible, which is a little too much for a small list.

You can use "itemCount".
child: ListView.builder(
itemCount: dayMatch.length,
itemBuilder: (context, index) {
return Card(
child: Row(
children: <Widget>[
Text(dayMatch[index].date),
Text(dayMatch[index].team1),
Text(dayMatch[index].time),
Text(dayMatch[index].team2),
],
),
);
},
),

Related

Flutter ListView with nested ListView throws RangeError for offscreen widgets

First time working in Flutter and not really a software wizard. I've built an app that connects to Firebase and retrieves a data structure as a Map (all after login). This works fine. However, the data is (kind of) a list of lists (or Map of Maps), etc. Basic structure is:
{
title1: {
item-A: {
0: line1,
1: line2,
2: line3,
},
item-B: {
0: line1,
1: line2,
2: line3,
}
},
title2: {
item-A: {
0: line1,
...
}
The schema can have more or fewer titles, items, and lines, but the structure is the same.
The code I've implemented gets the values from the database (Firebase Realtime Database) via FutureBuilder, formats the results, and displays them. Retrieving the results and the general display formatting works as intended, but I can only see one or two of the list widgets before a huge red box is displayed and I get the following error:
The following IndexError was thrown building:
RangeError (index): Index out of range: index should be less than 1: 1
If I run a Hot Refresh or Hot Reload, or just reload the browser, I get a few more rows of Widgets and the error changes to the next index increment:
The following IndexError was thrown building:
RangeError (index): Index out of range: index should be less than 4: 5
If I keep refreshing, eventually the whole list shows up and the error goes away. Obviously this is not the desired behavior, however. I've been working this and testing different approaches but I don't really understand what the issue is.
My code (with a couple of details left out) is as follows:
Widget build(BuildContext context) {
return Consumer<ApplicationState>(
builder: (context, appState, child) {
selectedIndex.add(-1);
return Scaffold(
...
body: FutureBuilder(
future: futureDataRetreiverFunction(),
builder: (BuildContext context, AsyncSnapshot<Map> snapshot) {
if (snapshot.connectionState == ConnectionState.done && snapshot.hasData) {
... // convert the snapshot.data here //
return Container(
...
child: ListView(
shrinkWrap: true,
children: [
Form(
key: _formKey,
child: Column(
children: [
ListView.builder(
scrollDirection: Axis.vertical,
controller: ScrollController(),
shrinkWrap: true,
itemCount: snapshotData.keys.length, // the data is a Map
itemBuilder: (BuildContext context, int index) =>
Column(
children: [
...
Row(
children: [
Text(snapshotData.keys.elementAt(index)),
]
),
Row(
children: [
Text(selectedIndex[index].toString())
]
),
Row(
children: [
Flexible(
fit: FlexFit.loose,
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 0, 10),
child: ListView.builder(
shrinkWrap: true,
primary: false,
itemCount: snapshotData.values.elementAt(index)[1].length,
itemBuilder: (BuildContext context, int index2) =>
Text(snaptshotData.values.elementAt(index)[1][index2])
)
)
)]
)
])
)
])
])
);
...
Vishal pointed out the answer in his first comment to this question. I am using "selectedIndex" as part of a setState({}) call to change some visuals as part of an onTap: () {} call. I was initiating the list with a simple initiation call earlier in the class (List selectedIndex = [];), but then was only adding 1 item to the index in the builder. However, in this case, there are a total of 6 items which get built (more/less in other scenarios), and that was throwing the index error. Which is why it would increment on reload (another seletedIndex.add(-1); was called). I dropped in a quick function to pre-populate the index based on the size of the snapshot data, along the lines of:
for (var counter=0; counter<snapshotData.keys.length; counter++) {
selectedIndex.add(-1);
}
This solved the index RangeError.

Autoscroll to a particular child in a column - Flutter

I'm having a Column widget which contain a list of widgets. And this column is inside a SingleChildScrollView. For some reasons I need to autoscroll to the third child of the column while clicking the floating button.
My code looks somewhat like this.
SingleChildScrollView(
child: Column(
children: [
Column(
children:[ getWidget1(), getWidget2(), getWidget3()],
),
],
),
),
Use ScrollablePositionedList instead.
Create the controller
final ItemScrollController itemScrollController = ItemScrollController();
Create scroll function
void scrollTo(int index) {
itemScrollController.scrollTo(index: index, duration: scrollDuration, curve: Curves.easeInOutCubic, alignment: 0);
}
Assign it to ListBuilder
ScrollablePositionedList.builder(
key: Key('builder $selected'), //attention
itemCount: itemlength,
itemScrollController: itemScrollController,
itemPositionsListener: itemPositionsListener,
itemBuilder: (context, index) {
return `yourWidgets`}
),
Call it
ElevatedButton(
onTap:()=> scrollTo("your index here"),
child:...)
you can see scroll_loop_auto_scroll: ^0.0.5 may be helpful

Flutter. Multiple heroes share same tag. ListView with buttons

Can't figure it out how to solve this problem. So, here is the simplest code which represents my problem:
Scaffold(
body: Stack(
children: <Widget>[
...
Scrollbar(
child: ListView.builder(
primary: false,
shrinkWrap: true,
itemCount: _mapBloc?.mapData?.companies?.count ?? 0,
itemBuilder: (context, index) {
final company = _mapBloc?.mapData?.companies?.data[index];
return InkWell(
child: Hero(
tag: company.id,
child: Card(
child: Container(
height: 50,
width: double.infinity,
),
),
),
onTap: () {
Navigator.of(context)
.pushNamed('/company', arguments: company)
.then(
(results) {
if (results is PopWithResults) {
PopWithResults popResult = results;
}
},
);
},
);
},
),
)
],
),
);
And stack trace:
The following assertion was thrown during a scheduler callback:
There are multiple heroes that share the same tag within a subtree.
Within each subtree for which heroes are to be animated (i.e. a PageRoute subtree), each Hero must
have a unique non-null tag.
...
The items count in ListView changes with every database request. If the size is up to 5 widgets in ListView, then clicking works correctly, as soon as the list expands to, for example, 8 elements, I get the error written above. With what it can be connected? I tried to use unique Hero tags, but this does not solve the problem.
I need some advice and hope you can help me. If you need more information, please, write the comment.
Thanks for your attention!

ListView inside Column throws error 'Vertical viewport was given unbounded height'

My question seems to be a duplicate of ListView inside Column causes 'Vertical viewport was given unbounded height' but the solution to add an Expanded or Flexible widget around the ListView doesn't work at all. It still throws the same error: Vertical viewport was given unbounded height.
var data = ['a','b','c','d'];
Column(
children: <Widget>[
ListView.builder(
itemCount: data.length,
itemBuilder: (ctx, i) {
return Row(
children: <Widget>[
Text(data[i], style: TextStyle(fontSize: 24 * Rat.rat, color: Colors.white)),
],
);
},
),
],
);
Obviously it can easily be fixed by adding a container around the ListView with a fixed height but there should be no need for that, I want it to be dynamically sized.
UPDATE:
Try something like this:
class Esempio1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("WAKAWAKA"),
),
body: Container(
child: Column(
children: <Widget>[
Text("eg1"),
Text("eg2"),
Text("eg3"),
Expanded(
child: ListView.builder(
itemCount: 20,
itemBuilder: (ctx,i){
return ListTile(title: Text("aaaaaa$i"),);
},
),
)
],
),
),
);
}
}
I just tried this code and it should do what you want.
The OP actually had the block of code posted contained inside another Column, that's why the Expanded wasn't working as it should when wrapped around the ListView. Wrapping the Column inside another Expanded solved the problem and made it all work as expected.
How about wrapping ListView builder in SingleChildScrollView and setting up its physics to
physics: NeverScrollableScrollPhysics(),

Flutter - Scrollable List of Widgets

I have a screen that displays a list of widgets, something like this:
Column(
children: listW,
),
The listW object is of type List<Widget>. The first index contains a ListTitle and all others are of type Card. The number of cards are added dynamically. Now the problem is that when the list has lets say 10 Card objects, it is hidden below the screen. I need some sort of a ScrollableView to contain my list. How can I do that since SingleChildScrollableView can bear only one widget. How can I deal with this issue?
Try changing you code to this
ListView(children: listW,)
You can use a ListView() for this.
ListView(
children: <Widget>[
//Your widgets
]
)
Keep in mind, that a list view renders all the items currently in the list, which means huge lists will cause performance issues. You can get around this using a ListView.builder, since this creates items as they are scrolled on the screen.
class FruitList extends StatelessWidget{
final List<String> fruits = [ "Apple", "Banana", "Pear", "Orange", "Kiwi" ];
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
padding: EdgeInsets.all(5),
child: ListView.builder(
itemBuilder: _buildFruitItem,
itemCount: fruits.length,
)
)
);
}
Widget _buildFruitItem( BuildContext context, int index ){
return Card(
child: Text( fruits[index] ),
);
}
}
You can checkout more documentation on this here: https://flutter.io/docs/cookbook/lists/long-lists