With the help of experienced users of this site, I was able to request data from a csv file and pass it to my application. In particular, when you click on the button, the text changes. First, this is the first item in the list, then the second one, and so on until the end. This is exactly what I need.
But the problem is that in the future it goes wrong. For example, if there are more than 10 items in the list, then the text does not change after the fifth item. If there are more than 100 items, then the problem starts after the 25th item, and so on. That is, it is impossible to reach the last item in the list.
Here is the complete code:
// CSV Experiment route
class CSVExperimentRoute extends StatelessWidget {
const CSVExperimentRoute({key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
debugShowCheckedModeBanner: false,
title: 'CSV Experiment',
home: ListFromCSV(),
);
}
}
class ListFromCSV extends StatefulWidget {
const ListFromCSV({Key? key}) : super(key: key);
@override
_ListFromCSVState createState() => _ListFromCSVState();
}
class _ListFromCSVState extends State<ListFromCSV> {
List<List<dynamic>> _listData = [
[""]
];
int _listCount = 0;
bool _isFirstLoad = true;
@override
initState() {
_loadCSV();
}
// This function is only triggered at init, so we only load csv once
void _loadCSV() async {
String _rawData = await rootBundle.loadString("files/Text.csv");
_listData = const CsvToListConverter().convert(_rawData);
}
// This function is triggered when my button is pressed
void _nextCSV() {
setState(() {
_listData = _listData;
_listCount < _listData[0].length - 1
? _isFirstLoad
? _isFirstLoad = false
: _listCount
: _listCount;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("My CSV Attempt"),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const SizedBox(height: 30),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0D47A1),
Color(0xFF1976D2),
Color(0xFF42A5F5),
],
),
),
),
),
TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.all(16.0),
primary: Colors.white,
textStyle: const TextStyle(fontSize: 20),
),
onPressed: _nextCSV,
child: const Text('Click me to change Text'),
),
],
),
),
const SizedBox(height: 30),
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Stack(
children: <Widget>[
Positioned.fill(
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
// Color(0xFF0D47A1),
// Color(0xFF1976D2),
// Color(0xFF42A5F5),
],
),
),
),
),
Text(
_listData[_listCount][0],
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontWeight: FontWeight.bold),
)
],
),
),
],
),
));
}
}
But I assume that the problem is in the part where the conditions are specified:
// This function is triggered when my button is pressed
void _nextCSV() {
setState(() {
_listData = _listData;
_listCount < _listData[0].length - 1
? _isFirstLoad
? _isFirstLoad = false
: _listCount
: _listCount;
});
}
Here is a small file for testing: FILE
Thanks in advance.
CodePudding user response:
The problem is not the 5th or 20th items. The problem is you are comparing the length of the list of the first item instead of the length of the list entire CSV. just remove the [0] it will work for you.
void _nextCSV() {
setState(() {
_listData = _listData;
_listCount < _listData.length - 1
? _isFirstLoad ? _isFirstLoad = false
: _listCount
: _listCount;
});
}
Hope this helps.