Generate gridView from an http request json response - flutter

the aim is to create a gridView of x elements, where x is dynamic because depends from the answer I receive from http request.
I know how to create a base gridView and how to print the result of my http request, but I've not understood how can I do both things: read json response, count how many elements I hava to create, create all elements with their names.
Here is the code:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'utils/Request.dart';
class MyGames extends StatelessWidget {
// ### Sono i parametri che invio al php nella richiesta
static var requestBody = {"action": "getMyGames", "id_utente": "1"};
Future<Response> richiesta = makeRequest(requestBody);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[850],
body:
GridView.count(crossAxisCount: 1, childAspectRatio: (2.5), children: [
FutureBuilder<Response>(
future: richiesta,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: new BoxDecoration(
color: Colors.green[200],
),
child: Center(
child: Text(
snapshot.data.result[0]['name'](),
style: TextStyle(
color: Colors.grey[800],
),
),
),
));
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
]),
);
}
}
Thanks!

I've solved this way:
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'utils/Request.dart';
class MyGames extends StatelessWidget {
// ### Sono i parametri che invio al php nella richiesta
static var requestBody = {"action": "getMyGames", "id_utente": "1"};
Future<Response> richiesta = makeRequest(requestBody);
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[850],
body: FutureBuilder<Response>(
future: richiesta,
builder: (context, snapshot) {
if (snapshot.hasData) {
final List<Widget> listone =
snapshot.data.result.map<Widget>((el) => tile(el)).toList();
return GridView.extent(
maxCrossAxisExtent: 250,
children: listone,
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
);
}
Widget tile(el) {
return Padding(
padding: EdgeInsets.all(10),
child: Container(
decoration: new BoxDecoration(
color: Colors.green[200],
),
child: Center(
child: Text(
el['nomeGioco'],
style: TextStyle(
color: Colors.grey[800],
),
), /*Center(
child: Text('Item $index',
style: Theme.of(context).textTheme.headline5)),*/
),
));
}
}

Related

How do i display progress bar on each item in the listview using flutter

i have a json data which am displaying in the listview that contains item name, scores and target scores. i want to show a progress bar indicating scored points and the target points below is my code and images to help understand.
This is my json data
Below is My code:
`
import 'dart:convert';
import 'package:network/network.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class FavouriteTab extends StatefulWidget {
#override
_FavouriteTabState createState() => _FavouriteTabState();
}
class _FavouriteTabState extends State<FavouriteTab> {
List products = List();
Future getAllProducts() async {
var response = await http.get(NetworkUrl.getProducts());
if (response.statusCode == 200) {
setState(() {
products = json.decode(response.body);
});
return products;
}
}
#override
void initState() {
super.initState();
getAllProducts();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Target Scores"),
),
body: FutureBuilder(
future: getAllProducts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
if (products.contains("empty")) {
return Center(child: Text("NO DATA"));
} else {
return ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
var notis = products;
var scoredAmt = notis[index]['scored_amt'];
var targetAmt = notis[index]['target_score'];
var _percentages = (scoredAmt / targetAmt);
return Card(
child: Container(
child: Column(
children: [
Text(notis[index]['item_name']),
Text(
notis[index]['target_score'],
style: TextStyle(color: Colors.indigo),
),
SizedBox(height: 5),
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Scored Amount :" +
notis[index]['scored_amt']),
),
Spacer(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Target Amount :" +
notis[index]['target_score']),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 300,
height: 30,
child: LinearProgressIndicator(
value: _percentages)),
),
],
),
),
);
});
}
} else {
return LinearProgressIndicator(
backgroundColor: Colors.purpleAccent,
);
}
}),
);
}
}`
Am getting this error
i want to have data display like this according to the scores:
This is how i want to display
I don't know what am doing wrong kindly help
As the error you are getting denotes it seems that you are not parsing the strings as num's and are trying to divide Strings.
var _percentages = (num.tryParse(scoredAmt) / num.tryParse(targetAmt))
Or even better do that parsing in your model see here.
Also you are calling the getAllProducts in initState but are not caching the result and you call it again in the futureBuilder,
import 'dart:convert';
import 'package:Habapay/network/network.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class FavouriteTab extends StatefulWidget {
#override
_FavouriteTabState createState() => _FavouriteTabState();
}
class _FavouriteTabState extends State<FavouriteTab> {
List products = List();
Future allProducts;
Future getAllProducts() async {
var response = await http.get(NetworkUrl.getProducts());
if (response.statusCode == 200) {
setState(() {
products = json.decode(response.body);
});
return products;
}
}
#override
void initState() {
super.initState();
allProducts= getAllProducts();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Target Scores"),
),
body: FutureBuilder(
future: allProducts,/// Now the future gets called only once
builder: (context, snapshot) {
if (snapshot.hasData) {
if (products.contains("empty")) {
return Center(child: Text("NO DATA"));
} else {
return ListView.builder(
itemCount: products.length,
itemBuilder: (context, index) {
var notis = products;
var scoredAmt = notis[index]['scored_amt'];
var targetAmt = notis[index]['target_score'];
var _percentages = (scoredAmt / targetAmt);
return Card(
child: Container(
child: Column(
children: [
Text(notis[index]['item_name']),
Text(
notis[index]['target_score'],
style: TextStyle(color: Colors.indigo),
),
SizedBox(height: 5),
Row(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Scored Amount :" +
notis[index]['scored_amt']),
),
Spacer(),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text("Target Amount :" +
notis[index]['target_score']),
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 300,
height: 30,
child: LinearProgressIndicator(
value: _percentages)),
),
],
),
),
);
});
}
} else {
return LinearProgressIndicator(
backgroundColor: Colors.purpleAccent,
);
}
}),
);
}
}`

display alert when data is changed using flutter?

My screen look like thisI have trying to display alert when snapshot.data value has been changed.i try the if else condition
import 'dart:async';
import 'dart:convert';
import 'package:assets_audio_player/assets_audio_player.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
import'package:flutter_custom_clippers/flutter_custom_clippers.dart';
import 'package:tv_dashboard/pages/test.dart';
//import 'package:assets_audio_player/assets_audio_player.dart';
class DashBoard extends StatefulWidget {
#override
_DashBoardState createState() => _DashBoardState();
}
var now = new DateTime.now();
String g = ('${now.day}-${now.month}-${now.year}');
AnimationController _controller;
Animation<double> _animation;
class _DashBoardState extends State<DashBoard> with TickerProviderStateMixin {
Timer timer;
int counter = 0;
Test data = Test();
Future<List<dynamic>> fetchUsers() async {
String url = 'http://us.rdigs.com/jsonData.php';
var result = await http.get(url, headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
});
if (result.statusCode == 200) {
//print(result.body);
//playSound();
return json.decode(result.body);
} else {
// If the server not return a 200 OK ,
// then throw the exception.
throw Exception('Failed');
}
}
playSound() async {
AssetsAudioPlayer audioPlayer = AssetsAudioPlayer();
audioPlayer.open(Audio('assets/Ring.mp3'));
}
String name(dynamic name) {
return name['name'];
}
String leads(dynamic leads) {
return leads['leads'];
}
#override
void initState() {
super.initState();
timer = Timer.periodic(Duration(seconds: 5), (Timer t) => addValue());
}
void addValue() {
setState(() {
//playSound();
counter++;
});
}
void alertBox() async {
await fetchUsers();
Container(
padding: EdgeInsets.only(left: 300),
child: AlertDialog(
title: Text('Alert Data'),
),
); //Use the response in the dialog
}
var totalLeads = 0;
var countLead = 0;
var allLeads;
#override
Widget build(BuildContext context) {
alertBox();
//playSound();
return Scaffold(
// backgroundColor: Color.fromRGBO(198, 159, 169, 1),
body: Column(
children: [
ClipPath(
clipper: OvalBottomBorderClipper(),
child: Container(
padding: EdgeInsets.only(top: 5),
height: 70,
color: Colors.cyan[100],
child: Center(
child: Column(
children: [
Text(
"Total Leads",
style: new TextStyle(fontSize: 28.0, fontFamily: 'Michroma'),
),
Text(
totalLeads.toString(),
style: new TextStyle(
fontSize: 25.0,
),
)
],
)),
),
),
Expanded(
child: FutureBuilder<List<dynamic>>(
future: fetchUsers(),
builder: (context, snapshot) {
if (snapshot.hasData) {
//total leads
//alertBox();
totalLeads = snapshot.data
.map<int>((m) => int.parse(m["leads"]))
.reduce((a, b) => a + b);
return GridView.builder(
itemCount: snapshot.data.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 6,
childAspectRatio:
MediaQuery.of(context).size.height / 350,
),
padding: EdgeInsets.all(8),
itemBuilder: (BuildContext context, int index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
bottomRight: Radius.circular(20)),
side: BorderSide(color: Colors.black)),
child: Column(
children: <Widget>[
Container(
padding: EdgeInsets.only(top: 10),
child: Column(
children: [
Text(
name(snapshot.data[index]),
style: new TextStyle(
fontSize: 25.0,
),
),
Container(
padding: EdgeInsets.only(top: 12),
child: Text(
leads(snapshot.data[index])
.toString(),
style: new TextStyle(
fontSize: 26.0,
color: Colors.blue),
))
],
)),
],
),
);
});
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
} else {
return Center(child: CircularProgressIndicator());
}
}))
],
));
}
}
totalLeads is count of my all int value
sum is temp variable
my problem is when data is changed in json string then display the alert box in flutter
When data changed in string, you can show AlertDialog widget:
Future<void> showErrorDialog() async {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Error'),
content: SingleChildScrollView(
child: Text(
'Error message',
),
),
actions: <Widget>[
TextButton(
child: Text('Ok'),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
}

Flutter Cannot show List item in Drawar

I am new to flutter.
I am trying to create list view dynamically using server response JSON data using futureBuilder. The code writen by me while wathing YouTube videos, but I can't understand what is the mistake.
//It looks like your post is mostly code; please add some more details.//
main.dart
import 'package:flutter/material.dart';
import 'home.dart';
void main() {
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
home: home(),
));
}
home.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
class home extends StatefulWidget {
home({Key key}):super();
#override
homepage createState() =>new homepage();
}
class homepage extends State<home>{
Color theme = Colors.lightBlue;
Color theme_text = Colors.white;
Future<List<category>> _getCategory() async {
var data = await http
.get("https://next.json-generator.com/api/json/get/VJ6EHYFO_");
debugPrint(data.body);
var jsondata = json.decode(data.body);
List<category> list = [];
for (var u in jsondata) {
category c = category(u['name'], u['id']);
list.add(c);
}
return list;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: theme,
title: Text('SIMS Home Page'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.shopping_cart),
onPressed: () => debugPrint("search pressed"),
)
],
),
drawer: Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Text(
"Not Signed",
textAlign: TextAlign.center,
style: TextStyle(color: theme_text, fontSize: 20),
),
decoration: BoxDecoration(
color: theme,
),
),
FutureBuilder(
future: _getCategory(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text("Loading..."),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text(snapshot.data[index]),);
});
}
},
),
],
),
),
);
}
class category {
final name;
final id;
category(this.name, this.id);
}
You have to use shrinkwrap property of listView.builder to get it work. it will allow listview to grow only that much which is require.
Moreover, in text view you are assigning items directly you have to access name and id individually as shown in below code.
Container(
height: 150,
child: DrawerHeader(
child: Text(
"Not Signed",
textAlign: TextAlign.center,
style: TextStyle(color: theme_text, fontSize: 20),
),
decoration: BoxDecoration(
color: theme,
),
),
),
FutureBuilder(
future: _getCategory(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text("Loading..."),
),
);
} else {
return Container(
height: MediaQuery.of(context).size.height - 150,
child: ListView.builder(
shrinkWrap: true, //added line
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(snapshot.data[index]
.toString()), //accessing name from json
);
}),
);
}
},
),

how to listen to two different futures on one screen?

I am learning flutter and building a simple vocabulary app. I have one future coming from sqlLite database and another from twitter api. I only know how to create one state class with builder.
So the _tweet method, I need to have it show up in the placeholder/hard coded tweet spot. It doesn't work though.
import 'package:flutter/material.dart';
import '../../resources/dbprovider.dart';
import '../../resources/tweetprovider.dart';
import '../../data/models/word.dart';
import 'package:tweet_webview/tweet_webview.dart';
class WordCard extends StatefulWidget {
final int id;
WordCard({
this.id,
});
#override
State<StatefulWidget> createState() {
return _WordCardState();
}
}
class _WordCardState extends State<WordCard> {
#override
Widget build(BuildContext context) {
final dbProvider = DBProvider.get();
return Scaffold(
appBar: AppBar(
title: Text('Meme Vocab'),
),
body: FutureBuilder<Word>(
future: dbProvider.getWordByID(widget.id),
builder: (context, snapshot) {
if (snapshot.hasData) {
Word word = snapshot.data;
return _card(word);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}));
}
Widget _card(Word word) {
return Padding(
padding: EdgeInsets.all(15.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
word.word.trim(),
style: new TextStyle(
fontFamily: "Roboto",
fontSize: 40.0,
fontWeight: FontWeight.bold,
color: Colors.black.withOpacity(0.45)),
textAlign: TextAlign.left,
),
Text(
word.definition,
style: new TextStyle(
fontFamily: "Roboto",
fontSize: 20.0,
fontStyle: FontStyle.italic),
textAlign: TextAlign.left,
),
TweetWebView.tweetUrl(
"https://twitter.com/realDonaldTrump/status/1159898199802425344") //placeholder
],
),
);
}
}
//Don't know where to put this widget so it renders, how to return the tweets I fetch.
Future<Widget> _tweet(Word word) async {
final tweetProvider = TweetProvider();
List<int> tweets = await tweetProvider.getRelevantTweetIDs(word);
final list = ListView.builder(
scrollDirection: Axis.vertical,
padding: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
itemCount: tweets.length,
itemBuilder: (context, index) {
var tweetID = tweets[index].toString();
return Card(
child: TweetWebView.tweetID(tweetID),
);
},
);
final container =
Container(color: Colors.black26, child: Center(child: list));
return container;
}
I found that Future Builder widget is the way to go. I have it in the place of the TweetWebView or basically I can place it anywhere there is a widget whose's contents are a future.
FutureBuilder(
future: tweetProvider.getRelevantTweetIDs(word),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
print('something went wrong while fetching tweets');
}
return Expanded(child: _tweetList(snapshot.data));
} else {
return Center(child: CircularProgressIndicator());
}
},
)

RefreshIndicator not working on FutureBuilder?

Here's my full code
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:weathercheck/Weather.dart';
import 'dart:convert';
Here's where i connect my WeatherData Class
Future<WeatherData> fetchWeatherdetail() async {
final response =
await http.get('http://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22');
if (response.statusCode == 200) {
// If server returns an OK response, parse the JSON.
return WeatherData.fromJson(json.decode(response.body));
} else {
// If that response was not OK, throw an error.
throw Exception('Failed to load post');
}
}
void main(){
runApp(MaterialApp(
initialRoute: '/',
routes: {
'/' : (context) => MyHome(),
'/weatherResult' : (context) => WeatherResult1()
}
)
);
}
Widget myAppBar(String txtTitle){
return AppBar(
title: Text(txtTitle),
backgroundColor: Colors.orange[300],
);
}
class MyHome extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: myAppBar('Find your city weather'),
body: Column(children:[
TextField(
onChanged: (text){
},
),
RaisedButton(
child: Text('Search'),
onPressed: (){
Navigator.pushNamed(context, '/weatherResult');
},
),
],)
);
}
}
class _WeatherResult1State extends State<WeatherResult1>{
final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey =
new GlobalKey<RefreshIndicatorState>();
Future<WeatherData> weatherData;
#override
void initState() {
super.initState();
weatherData = fetchWeatherdetail();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: myAppBar('Find your city weather'),
body:
From here want to refresh but not working
RefreshIndicator(
key: _refreshIndicatorKey,
onRefresh: _refresh,
child:
FutureBuilder<WeatherData>(
future: fetchWeatherdetail(),
builder: (context, snapshot) {
if (snapshot.hasData) {
for(var i = 0; i< snapshot.data.weather.length ; i++){
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
image: AssetImage('assets/images/london.jpg'),
fit: BoxFit.fill
)
),
child:Row(
children:<Widget>[
Column(
children: <Widget>[
Text('City ID: ', style: TextStyle(fontSize: 20,),),
Text('City Name: ', style: TextStyle(fontSize: 20),),
Text('Weather condition: ', style: TextStyle(fontSize: 20),),
Text('Weather description: ', style: TextStyle(fontSize: 20),)
],),
Column(children: <Widget>[
Text(snapshot.data.id.toString(), style: TextStyle(fontSize: 20),),
Text(snapshot.data.name, style: TextStyle(fontSize: 20),),
Text(snapshot.data.weather[i].main, style: TextStyle(fontSize: 20),),
Text(snapshot.data.weather[i].description, style: TextStyle(fontSize: 20), )
],),
]));
}
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
// By default, show a loading spinner.
return Center(
child: CircularProgressIndicator()
);
},
)
)
);
}
Here's my _refresh function
Future<Null> _refresh() async{
await Future.delayed(Duration(seconds: 2));
setState(() {
weatherData = fetchWeatherdetail();
}
);
return null;
}
}
i dont know what makes this code not working, is it refreshIndicator not working with Future builder? or something else.. im really stucking here.. and also why this stackoverflow so hard to make thread ah..
It looks that you should be using a ListView to show all your wheater items in your list. Replace the following code
for(var i = 0; i< snapshot.data.weather.length ; i++){
return Container(
decoration: BoxDecoration(
...
with
return ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
itemBuilder: (context, i){
WeatherData weatherItem = snapshot.data.weather[i];
return Container(
decoration: BoxDecoration(
...
},
itemCount: snapshot.data.weather.length,
);