Related
I can't fetch the next address
but I can fetch sequence shipto 0
RangeError (index): Invalid value: Only valid value is 0: 1
after some fixes type 'sting' is not a subtype of type 'int' of 'index'
The data in the address will be included in the same set of items.
Please help me I am practicing fetch api
List<dynamic> pos = <dynamic>[];
bool isLoading = false;
#override
void initState() {
super.initState();
this.fetchMos();
}
Future fetchMos() async {
var client = http.Client();
String mosUrl =
',';
var url = Uri.parse(mosUrl);
var headers = {'Client-Token': ''};
var response = await client.get(url, headers: headers);
if (response.statusCode == 200) {
var items = jsonDecode((utf8.decode(response.bodyBytes)))['items'];
setState(() {
pos = items;
isLoading = false;
});
} else {
setState(() {
pos = [];
isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
),
body: ListView.builder(
itemBuilder: (context, index) {
if (pos.length > 0) {
return _listItem(index);
} else {
return Center(child: CircularProgressIndicator());
}
},
itemCount: pos.length + 1,
),
);
}
_listItem(index) {
return Card(
child: ListTile(
leading: const CircleAvatar(
child: Icon(Icons.emoji_emotions),
),
title: Text(
pos[index]['addr1'],
style: const TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
pos[index]['shipto'],
),
),
);
}
{
"items": [
{
"custnum": "",
"name": "",
"address": [
{
"shipto": 0,
"addr1": "",
"thanon": "",
"tambon": "",
"amphur": "",
"prov_code": "",
"province": "",
"zipcode": "",
"country": "",
"contact": "",
"postcode": ""
},
{
"shipto": 1,
"addr1": "",
"thanon": "",
"tambon": "",
"amphur": "",
"prov_code": "",
"province": "",
"zipcode": "",
"country": "",
"contact": "",
"postcode": ""
},
{
"shipto": 2,
"addr1": "",
"thanon": "",
"tambon": "",
"amphur": "",
"prov_code": "",
"province": "",
"zipcode": "",
"country": "",
"contact": "",
"postcode": ""
},
{
"shipto": 3,
"addr1": "",
"thanon": "",
"tambon": "",
"amphur": "",
"prov_code": "",
"province": "",
"zipcode": "",
"country": "",
"contact": "",
"postcode": ""
}
]
}
],
"total_records": 1,
"total_pages": 1,
"current_page": 1
Currently your variable pos does not contain addresses. You should add the following code after var items = jsonDecode((utf8.decode(response.bodyBytes)))['items'];
var addresses = (items[0] as Map<String, dynamic>)['address'] as List;
setState(() {
pos = addresses;
loading = false;
});
Then in ListView.builder change parameter itemCount to pos.length.
Lastly, you are trying to give integer as parameter to Text widget, which only accepts String, so change current code to the following.
Text(
pos[index]['shipto'].toString(),
)
Remark: Learn about data models and JSON serialization in Dart, don't use map/json, but try using models.
If you set the itemCount of ListView.builder widget, you'll get an index error.
Try changing your code to this
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0.0,
),
body: ListView.builder(
itemBuilder: (context, index) {
if (pos.length > 0) {
return _listItem(index);
} else {
return Center(child: CircularProgressIndicator());
}
},
itemCount: pos.length, // change here
),
);
}
how to select one checkbox in each answer for each question. so that each question can only be chosen one answer. this is my data and this is my code
This is data example:
List<dynamic> survey = [
{
"id": 1,
"question":"Question1",
"answer": [
{"id": 1, "name": "Option A"},
{"id": 2, "name": "Option B"},
{"id": 3, "name": "Option C"},
{"id": 4, "name": "Option D"}
],
},
{
"id": 2,
"question":
"Question2",
"answer": [
{"id": 1, "name": "Option A"},
{"id": 2, "name": "Option B"},
{"id": 3, "name": "Option C"},
{"id": 4, "name": "Option D"}
],
},
];
This is my code:
bool isSelected = false;
onSelected(value) {
setState(() {
isSelected = value!;
});
}
#override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: survey.length,
itemBuilder: (BuildContext context, int index) {
var number = index + 1;
var listAnswer = survey[index]["answer"];
return Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.9,
child: Text(
survey[index]["question"],
maxLines: 5,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(height: 10),
ListView.builder(
shrinkWrap: true,
itemCount: listAnswer.length,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.only(bottom: 10),
child: ListTile(
title: Text(listAnswer[index]["name"]),
trailing: Checkbox(
checkColor: Colors.white,
value: isSelected,
shape: CircleBorder(),
onChanged: (bool? value) {
onSelected(value);
},
),
),
);
},
)
],
),
);
},
);
}
It would be easier with model class. I am using a map to store the selected answer.
Map<String, int> selectedAnswer = {};
Method checking whether current answer is selected or not.
bool isSelected(String qustion, int answerID) {
if (selectedAnswer.containsKey(qustion) &&
selectedAnswer[qustion] == answerID) {
return true;
}
return false;
}
And switching value
onChanged: (bool? value) {
if (_isSelected) {
selectedAnswer[question] =
listAnswer[index]["id"];
} else {
selectedAnswer
.addAll({question: listAnswer[index]["id"]});
}
setState(() {});
},
Full widget.
class TEL extends StatefulWidget {
const TEL({super.key});
#override
State<TEL> createState() => _TELState();
}
class _TELState extends State<TEL> {
List<dynamic> survey = [
{
"id": 1,
"question": "Question1",
"answer": [
{"id": 1, "name": "Option A"},
{"id": 2, "name": "Option B"},
{"id": 3, "name": "Option C"},
{"id": 4, "name": "Option D"}
],
},
{
"id": 2,
"question": "Question2",
"answer": [
{"id": 1, "name": "Option A"},
{"id": 2, "name": "Option B"},
{"id": 3, "name": "Option C"},
{"id": 4, "name": "Option D"}
],
},
];
Map<String, int> selectedAnswer = {};
bool isSelected(String qustion, int answerID) {
if (selectedAnswer.containsKey(qustion) &&
selectedAnswer[qustion] == answerID) {
return true;
}
return false;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(8),
itemCount: survey.length,
itemBuilder: (BuildContext context, int index) {
var number = index + 1;
final question = survey[index]["question"];
List<Map> listAnswer = survey[index]["answer"];
return Container(
padding: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: MediaQuery.of(context).size.width * 0.9,
child: Text(
question,
maxLines: 5,
overflow: TextOverflow.ellipsis,
),
),
SizedBox(height: 10),
ListView.builder(
shrinkWrap: true,
itemCount: listAnswer.length,
itemBuilder: (BuildContext context, int index) {
final bool _isSelected =
isSelected(question, listAnswer[index]["id"]);
return Container(
margin: EdgeInsets.only(bottom: 10),
child: ListTile(
title: Text(listAnswer[index]["name"].toString()),
trailing: Checkbox(
checkColor: Colors.white,
value: _isSelected,
shape: CircleBorder(),
onChanged: (bool? value) {
if (_isSelected) {
selectedAnswer[question] =
listAnswer[index]["id"];
} else {
selectedAnswer
.addAll({question: listAnswer[index]["id"]});
}
setState(() {});
},
),
),
);
},
)
],
),
);
},
),
);
}
}
I have this code file that loads audio playlist files to the media player direct from the internet. So, I want to change instead of loading audio playlist files direct from the internet I want it to fetch from my GraphQL API using graphql_flutter 5.1.0 (https://pub.dev/packages/graphql_flutter) package from zino.company.
My question is how can I query the list of episodes to populate the _playlist AudioSource before the page loads completely?
I tried to use didChangeDependencies but the playlist was not populated after the page loaded. Also, the Tested hard code that I commented on the file works but still it is hard coded. When the playlist is loaded, the audio files are playable and all the buttons work. I have attached the media_player.dart file and snapshot of the app.
My GraphQL API request and response for the episodes is as follow;
graphql request
{
episodeByPodcast(podcast: 1){
id
title
synopsis
duration
filePath
host
guest
podcast {
id
podcastTitle
}
recorded
posted
}
}
graphql response
{
"data": {
"episodeByPodcast": [
{
"id": "1",
"title": "Episode 1",
"synopsis": "Hello World",
"duration": "18:59",
"filePath": "podcasts/episode_1.mp3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-27",
"posted": "2022-05-27"
},
{
"id": "4",
"title": "Episode 2",
"synopsis": "Hello World",
"duration": "18:59",
"filePath": "podcasts/episode_2.mp3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-27",
"posted": "2022-05-27"
},
{
"id": "5",
"title": "Episode 3",
"synopsis": "Hello World",
"duration": "41:02",
"filePath": "podcasts/episode_3",
"host": "John Doe",
"guest": "Jane Doe",
"podcast": {
"id": "1",
"podcastTitle": "Season 1"
},
"recorded": "2022-05-28",
"posted": "2022-05-28"
}
]
}
}
The media_player.dart file
import 'package:audio_service/audio_service.dart';
import 'package:audio_session/audio_session.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:just_audio/just_audio.dart';
import 'package:just_audio_background/just_audio_background.dart';
import 'package:provider/provider.dart';
import 'package:rxdart/rxdart.dart';
import 'package:app/screens/podcast/widgets/common.dart';
import 'widgets/control_buttons.dart';
// Tested hard code
// const pathPrefix = MediaEndpoint.url;
// final List<Map<String, dynamic>> episodes = [
// {
// "id": "1",
// "title": "Episode 1",
// "synopsis": "Hello World",
// "duration": "18:59",
// "filePath":
// "podcasts/episode_1.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-27",
// "posted": "2022-05-27"
// },
// {
// "id": "4",
// "title": "Episode 2",
// "synopsis": "Hello World",
// "duration": "18:59",
// "filePath":
// "podcasts/episode_2.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-27",
// "posted": "2022-05-27"
// },
// {
// "id": "5",
// "title": "Episode 3",
// "synopsis": "Hello World",
// "duration": "41:02",
// "filePath": "podcasts/episode_3.mp3",
// "host": "John Doe",
// "guest": "Jane Doe",
// "podcast": {"id": "1", "podcastTitle": "Season 1"},
// "recorded": "2022-05-28",
// "posted": "2022-05-28"
// }
// ];
// final ConcatenatingAudioSource _playlist = ConcatenatingAudioSource(
// children: [
// for (var episode in episodes)
// AudioSource.uri(
// Uri.parse('$pathPrefix${episode['filePath']}'),
// tag: MediaItem(
// id: episode['id'].toString(),
// album: episode['podcast']['podcastTitle'].toString(),
// title: episode['title'].toString(),
// artUri: Uri.parse(
// "https://mywebsite.com/uploads/2021/04/cover-art.png"),
// ),
// ),
// ],
// );
// - End of Tested hard code -
class MediaPlayer extends StatefulWidget {
static const routeName = '/media-player';
#override
_MediaPlayerState createState() => _MediaPlayerState();
}
class _MediaPlayerState extends State<MediaPlayer> {
var _isInit = true;
var _isLoading = false;
#override
void didChangeDependencies() {
if (_isInit) {
setState(() {
_isLoading = true;
});
setState(() {
_isLoading = false;
});
}
_isInit = false;
super.didChangeDependencies();
}
static int _nextMediaId = 0;
late AudioPlayer _player;
final _playlist = ConcatenatingAudioSource(
children: [
ClippingAudioSource(
start: const Duration(seconds: 60),
end: const Duration(seconds: 90),
child: AudioSource.uri(Uri.parse(
"https://mywebsite.com/podcasts/episode_1.mp3")),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "A Salute To Head-Scratching Science (30 seconds)",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse("https://mywebsite.com/podcasts/episode_2.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "A Salute To Head-Scratching Science",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse(
"https://mywebsite.com/podcasts/episode_3.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Science Friday",
title: "From Cat Rheology To Operatic Incompetence",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
AudioSource.uri(
Uri.parse(
"https://mywebsite.com/podcasts/episode_4.mp3"),
tag: MediaItem(
id: '${_nextMediaId++}',
album: "Public Domain",
title: "Nature Sounds",
artUri: Uri.parse(
"https://mywebsite.com/uploads/2021/04/cover-art.png"),
),
),
],
);
final int _addedCount = 0;
#override
void initState() {
super.initState();
_player = AudioPlayer();
SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
statusBarColor: Colors.black,
));
_init();
}
Future<void> _init() async {
final session = await AudioSession.instance;
await session.configure(const AudioSessionConfiguration.speech());
// Listen to errors during playback.
_player.playbackEventStream.listen((event) {},
onError: (Object e, StackTrace stackTrace) {
print('A stream error occurred: $e');
});
try {
await _player.setAudioSource(_playlist);
} catch (e, stackTrace) {
// Catch load errors: 404, invalid url ...
print("Error loading playlist: $e");
print(stackTrace);
}
}
#override
void dispose() {
_player.dispose();
super.dispose();
}
Stream<PositionData> get _positionDataStream =>
Rx.combineLatest3<Duration, Duration, Duration?, PositionData>(
_player.positionStream,
_player.bufferedPositionStream,
_player.durationStream,
(position, bufferedPosition, duration) => PositionData(
position, bufferedPosition, duration ?? Duration.zero));
#override
Widget build(BuildContext context) {
final playerData = ModalRoute.of(context)!.settings.arguments as Map;
return _isLoading
? const CircularProgressIndicator()
: Scaffold(
appBar: AppBar(
title: Text(
playerData['title'],
),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: StreamBuilder<SequenceState?>(
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
if (state?.sequence.isEmpty ?? true) {
return const SizedBox();
}
final metadata = state!.currentSource!.tag as MediaItem;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Center(
child: Image.network(
metadata.artUri.toString())),
),
),
Text(metadata.album!,
style: Theme.of(context).textTheme.headline6),
Text(metadata.title),
],
);
},
),
),
ControlButtons(_player),
StreamBuilder<PositionData>(
stream: _positionDataStream,
builder: (context, snapshot) {
final positionData = snapshot.data;
return SeekBar(
duration: positionData?.duration ?? Duration.zero,
position: positionData?.position ?? Duration.zero,
bufferedPosition:
positionData?.bufferedPosition ?? Duration.zero,
onChangeEnd: (newPosition) {
_player.seek(newPosition);
},
);
},
),
const SizedBox(height: 8.0),
Row(
children: [
StreamBuilder<LoopMode>(
stream: _player.loopModeStream,
builder: (context, snapshot) {
final loopMode = snapshot.data ?? LoopMode.off;
const icons = [
Icon(Icons.repeat, color: Colors.grey),
Icon(Icons.repeat, color: Colors.orange),
Icon(Icons.repeat_one, color: Colors.orange),
];
const cycleModes = [
LoopMode.off,
LoopMode.all,
LoopMode.one,
];
final index = cycleModes.indexOf(loopMode);
return IconButton(
icon: icons[index],
onPressed: () {
_player.setLoopMode(cycleModes[
(cycleModes.indexOf(loopMode) + 1) %
cycleModes.length]);
},
);
},
),
Expanded(
child: Text(
"Playlist",
style: Theme.of(context).textTheme.headline6,
textAlign: TextAlign.center,
),
),
StreamBuilder<bool>(
stream: _player.shuffleModeEnabledStream,
builder: (context, snapshot) {
final shuffleModeEnabled = snapshot.data ?? false;
return IconButton(
icon: shuffleModeEnabled
? const Icon(Icons.shuffle,
color: Colors.orange)
: const Icon(Icons.shuffle, color: Colors.grey),
onPressed: () async {
final enable = !shuffleModeEnabled;
if (enable) {
await _player.shuffle();
}
await _player.setShuffleModeEnabled(enable);
},
);
},
),
],
),
SizedBox(
height: 240.0,
child: StreamBuilder<SequenceState?>(
stream: _player.sequenceStateStream,
builder: (context, snapshot) {
final state = snapshot.data;
final sequence = state?.sequence ?? [];
return ReorderableListView(
onReorder: (int oldIndex, int newIndex) {
if (oldIndex < newIndex) newIndex--;
_playlist.move(oldIndex, newIndex);
},
children: [
for (var i = 0; i < sequence.length; i++)
Dismissible(
key: ValueKey(sequence[i]),
background: Container(
color: Colors.redAccent,
alignment: Alignment.centerRight,
child: const Padding(
padding: EdgeInsets.only(right: 8.0),
child:
Icon(Icons.delete, color: Colors.white),
),
),
onDismissed: (dismissDirection) {
_playlist.removeAt(i);
},
child: Material(
color: i == state!.currentIndex
? Colors.grey.shade300
: null,
child: ListTile(
title:
Text(sequence[i].tag.title as String),
onTap: () {
_player.seek(Duration.zero, index: i);
},
),
),
),
],
);
},
),
),
],
),
),
);
}
}
App screenshot
media player app screenshot
I want to multiple values in a List.
For example I have below json which I decode in a customList List :
"cars": [
{ "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
{ "name":"BMW", "models":[ "320", "X3", "X5" ] },
{ "name":"Fiat", "models":[ "500", "Panda" ] }
]
I want to get the updated list when user searches for some keyword. The keywords can also contain name of car or model. How can I do this. Below is the code where I am successfully searching in names only.
List<Cars> updatedList = List<Cars>();
_onChanged(String value) {
setState(() {
updatedList = carsList
.where((string) => string.name.contains(value.toLowerCase()))
.toList();
});
}
class HomeState extends State<Home> {
Map carsMap = {
"cars": [
{
"name": "Ford",
"models": ["Fiesta", "Focus", "Mustang"]
},
{
"name": "BMW",
"models": ["320", "X3", "X5"]
},
{
"name": "Fiat",
"models": ["500", "Panda"]
}
]
};
List<Map> carsList = [];
String query1 = '';
#override
void initState() {
super.initState();
carsList = carsMap['cars'];
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Seperate List'),
),
body: Container(
padding: EdgeInsets.fromLTRB(5, 10, 5, 10),
child: Column(mainAxisSize: MainAxisSize.min, children: [
TextField(
onChanged: (s) {
query1 = s;
},
decoration: InputDecoration(
hintText: 'Filter Seacrh...',
suffixIcon: IconButton(
icon: Icon(Icons.search, color: Colors.black),
onPressed: () {
showFiltered();
}))),
ListView.builder(
shrinkWrap: true,
itemCount: carsList.length,
itemBuilder: (con, ind) {
return ListTile(
title: Text(carsList[ind]['name'],
style: TextStyle(
color: Colors.black,
)));
})
])));
}
showFiltered() {
List<Map> updatedList = carsList.where(
(m) => m.toString().toLowerCase().contains(query1.toLowerCase())).toList();
showDialog(
context: context,
builder: (con) {
return Dialog(
child: ListView.builder(
shrinkWrap: true,
itemCount: updatedList.length,
itemBuilder: (con, ind) {
return ListTile(
title: Text(updatedList[ind]['name'],
style: TextStyle(
color: Colors.black,
)));
}));
});
}
}
i have grid view shows all data in list and i have drop down with values like price from low to high and when user select any value then i will re-sort the list at this point all is work correctly and list updated but grid view stell with old list.
i cannot update grid view
class ProductsListState extends State<ProductsList> {
double width;
String _title;
String _selectedSort;
String _language;
ProductsListState(this._title);
List productsList;
int filter;
#override
Widget build(BuildContext context) {
MediaQueryData deviceInfo = MediaQuery.of(context);
width = deviceInfo.size.width;
_language = _language ?? AppLocalizations.of(context).tr('lang');
filter = filter ?? 1;
_selectedSort ??= getSortFilter(_language)[0];
productsList = (productsList ?? getProductsList(filter));
print(productsList);
print(filter);
var size = MediaQuery.of(context).size;
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Color.fromRGBO(205, 14, 64, 1),
appBar:
MarketinoAppBar(title: _title, width: width, appContext: context),
body: Stack(
children: <Widget>[
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
blurRadius: 13.0,
color: Colors.black.withOpacity(.5),
offset: Offset(6.0, 7.0),
),
],
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20)),
),
),
Column(
children: <Widget>[
Padding(
padding: EdgeInsetsDirectional.fromSTEB(0, 0, 20, 0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text('SORT BY: '),
DropdownButton<String>(
value: _selectedSort,
onChanged: (value) {
setState(() {
productsList.sort(
(a, b) => a['price'].compareTo(b['price']));
_selectedSort = value;
filter = 2;
});
},
items: getSortFilter(_language).map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
],
),
),
Container(
child: filter == 1
? Grid(productsList, width, size)
: Grid(getProductsList(2), width, size),
)
],
)
],
),
),
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
EasylocaLizationDelegate(locale: data.locale, path: "assets/language")
],
supportedLocales: [Locale('en', 'US'), Locale('ar', 'SA')],
locale: data.savedLocale,
),
);
}
//replace by json
List getProductsList(int filter) {
List list = [];
list.add({
"id": "1",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "110",
"quantity": "1",
"isLiked": "false",
"max": "5"
});
list.add({
"id": "2",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "112",
"quantity": "1",
"isLiked": "true",
"max": "5"
});
list.add({
"id": "3",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "114",
"quantity": "1",
"isLiked": "true",
"max": "10"
});
list.add({
"id": "4",
"name": "sssssssssssssssssssssssssssssssssssssssssssssssssssssssszzzzz",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "11",
"quantity": "1",
"isLiked": "false",
"max": "1"
});
list.add({
"id": "5",
"name": "sssss",
"imageUrl": "assets/images/Frozen Food.jpg",
"description": "qwerfghjhgfdsaasdfghnjmhgfdsa",
"price": "110",
"quantity": "1",
"isLiked": "false",
"max": "15"
});
switch (filter) {
case 1:
list.sort((a, b) => a['id'].compareTo(b['id']));
break;
case 2:
list.sort((a, b) => a['price'].compareTo(b['price']));
break;
}
return list;
}
List<String> getSortFilter(String language) {
if (language == 'english')
return [
"الأكثر رواجا",
"السعر من الأقل للأعلى",
"السعر من الأعلى للأقل",
"التخفيضات",
];
else
return [
"Popularty",
"Price: Low to High",
"Price: High to Low",
"Discount",
];
}
}
class Grid extends StatefulWidget {
List productsList;
var _width;
var _size;
Grid(this.productsList, this._width, this._size);
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return GridState(productsList, _width, _size);
}
}
class GridState extends State<Grid> {
List productsList;
var _width;
var _size;
GridState(this.productsList, this._width, this._size);
#override
Widget build(BuildContext context) {
// TODO: implement build
return Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: new GridView.builder(
itemCount: productsList.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: _width > 600 ? 3 : 2,
childAspectRatio: _width > 600 ? 0.6 : _width > 400 ? .725 : .685,
// childAspectRatio: (_itemWidth / _itemHeight),
),
itemBuilder: (BuildContext context, int index) {
return ProductGridTile(
price: double.parse(productsList[index]['price']),
width: _size.width,
image: productsList[index]['imageUrl'],
title: productsList[index]['name'],
likeStatus: productsList[index]['isLiked'] == 'true',
max: double.parse(productsList[index]['max']),
id: int.parse(productsList[index]['id']));
}),
),
);
}
}
gridview updated after re-sort list
You are doing some operations inside the build() method, when you call setState() these operations would be called again. Check that part and also try to update the list this way:
productsList = List.from(productsList)..sort(
(a, b) => a['price'].compareTo(b['price']));