In this blog post, I will show you how to make a football Scoreboard app using Flutter, for this tutorial we will use this API: https://www.api-football.com/
this is a nice tutorial where you will learn how to make an HTTP request from a REST API with flutter, so without further ado let's begin
Project Setup
so before we start coding there's two things that you must do
- sign up and get your API key
- add the HTTP package for flutter
after getting your API key open your Flutter project and open the pubspec.yaml file and add this dependency.
dependencies:
http: ^0.12.2
Now let's start coding.
Creating the API service class
first of all, we will create a new dart file and call it "api_manager.dart" In this class, we will create the function that will fetch the data for us.
code:
//before let's add the http package
import 'dart:convert';
import 'package:http/http.dart';
import 'package:soccer_tutorial/soccermodel.dart';
class SoccerApi {
//now let's set our variables
//first : let's add the endpoint URL
// we will get all the data from api-sport.io
// we will just change our endpoint
//the null means that the match didn't started yet
//let's fix that
final String apiUrl =
"https://v3.football.api-sports.io/fixtures?season=2020&league=39";
//In our tutorial we will only see how to get the live matches
//make sure to read the api documentation to be ables too understand it
// you will find your api key in your dashboard
//so create your account it's free
//Now let's add the headers
static const headers = {
'x-rapidapi-host': "v3.football.api-sports.io",
//Always make sure to check the api key and the limit of a request in a free api
'x-rapidapi-key': "PUT YOUR API KEY HERE OR IT WILL NOT WORK"
};
//Now we will create our method
//but before this we need to create our model
//Now we finished with our Model
Future<List<SoccerMatch>> getAllMatches() async {
Response res = await get(apiUrl, headers: headers);
var body;
if (res.statusCode == 200) {
// this mean that we are connected to the data base
body = jsonDecode(res.body);
List<dynamic> matchesList = body['response'];
print("Api service: ${body}"); // to debug
List<SoccerMatch> matches = matchesList
.map((dynamic item) => SoccerMatch.fromJson(item))
.toList();
return matches;
}
}
}
Now let's create the model class, In which we will store our data object for the different data of the API
so create a new file and call it soccermodel.dart and add this code
code:
class SoccerMatch {
//here we will see the different data
//you will find every thing you need in the doc
//I'm not going to use every data, just few ones
Fixture fixture;
Team home;
Team away;
Goal goal;
SoccerMatch(this.fixture, this.home, this.away, this.goal);
factory SoccerMatch.fromJson(Map<String, dynamic> json) {
return SoccerMatch(
Fixture.fromJson(json['fixture']),
Team.fromJson(json['teams']['home']),
Team.fromJson(json['teams']['away']),
Goal.fromJson(json['goals']));
}
}
//here we will store the fixture
class Fixture {
int id;
String date;
Status status;
Fixture(this.id, this.date, this.status);
factory Fixture.fromJson(Map<String, dynamic> json) {
return Fixture(json['id'], json['date'], Status.fromJson(json['status']));
}
}
//here we will store the Status
class Status {
int elapsedTime;
String long;
Status(this.elapsedTime, this.long);
factory Status.fromJson(Map<String, dynamic> json) {
return Status(json['elapsed'], json['long']);
}
}
//here we will store the Team data
class Team {
int id;
String name;
String logoUrl;
bool winner;
Team(this.id, this.name, this.logoUrl, this.winner);
factory Team.fromJson(Map<String, dynamic> json) {
return Team(json['id'], json['name'], json['logo'], json['winner']);
}
}
//here we will store the Goal data
class Goal {
int home;
int away;
Goal(this.home, this.away);
//Now we will create a factory method to copy the data from
// the json file
factory Goal.fromJson(Map<String, dynamic> json) {
return Goal(json['home'], json['away']);
}
}
Now we have almost finished we have only to create the UI of the app and call the fetch function
main.dart
import 'package:flutter/material.dart';
import 'package:soccer_tutorial/api_manager.dart';
import 'package:soccer_tutorial/pagerbody.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SoccerApp(),
);
}
}
class SoccerApp extends StatefulWidget {
@override
_SoccerAppState createState() => _SoccerAppState();
}
class _SoccerAppState extends State<SoccerApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFFAFAFA),
appBar: AppBar(
backgroundColor: Color(0xFFFAFAFA),
elevation: 0.0,
title: Text(
"SOCCERBOARD",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
//now we have finished the api service let's call it
//Now befo re we create Our layout let's create our API service
body: FutureBuilder(
future: SoccerApi()
.getAllMatches(), //Here we will call our getData() method,
builder: (context, snapshot) {
//the future builder is very intersting to use when you work with api
if (snapshot.hasData) {
print((snapshot.data).length);
return PageBody(snapshot.data);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}, // here we will buil the app layout
),
);
}
}
//So as we can see w got our matches data,
// the data size depend on the date and the time so
// you can get as many data as many matches are curetly playing
//Now let's try to get data by seasons and leagues
we need to create some widget in separate files like this
pagebody.dart
import 'package:flutter/material.dart';
import 'package:soccer_tutorial/goalstat.dart';
import 'package:soccer_tutorial/matchtile.dart';
import 'package:soccer_tutorial/teamstat.dart';
import 'soccermodel.dart';
Widget PageBody(List<SoccerMatch> allmatches) {
return Column(
children: [
Expanded(
flex: 2,
child: Container(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 18.0, vertical: 24.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
teamStat("Local Team", allmatches[0].home.logoUrl,
allmatches[0].home.name),
goalStat(allmatches[0].fixture.status.elapsedTime,
allmatches[0].goal.home, allmatches[0].goal.away),
teamStat("Visitor Team", allmatches[0].away.logoUrl,
allmatches[0].away.name),
],
),
),
),
),
Expanded(
flex: 5,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Color(0xFF4373D9),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(40.0),
topRight: Radius.circular(40.0),
),
),
child: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"MATCHES",
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
),
),
Expanded(
child: ListView.builder(
itemCount: allmatches.length,
itemBuilder: (context, index) {
return matchTile(allmatches[index]);
},
),
)
],
),
),
),
)
],
);
}
goalstat.dart file
import 'package:flutter/material.dart';
Widget goalStat(int expandedTime, int homeGoal, int awayGoal) {
var home = homeGoal;
var away = awayGoal;
var elapsed = expandedTime;
if (home == null) home = 0;
if (away == null) away = 0;
if (elapsed == null) elapsed = 0;
return Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
"${elapsed}'",
style: TextStyle(
fontSize: 30.0,
),
),
Expanded(
child: Center(
child: Text(
"${home} - ${away}",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 36.0,
),
),
),
)
],
),
);
}
matchstat.dart
import 'package:flutter/material.dart';
Widget teamStat(String team, String logoUrl, String teamName) {
return Expanded(
child: Column(
children: [
Text(
team,
style: TextStyle(
fontSize: 18.0,
),
),
SizedBox(
height: 10.0,
),
Expanded(
child: Image.network(
logoUrl,
width: 54.0,
),
),
SizedBox(
height: 10.0,
),
Text(
teamName,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 18.0,
),
),
],
),
);
}
matchtile.dart
import 'package:flutter/material.dart';
import 'soccermodel.dart';
Widget matchTile(SoccerMatch match) {
var homeGoal = match.goal.home;
var awayGoal = match.goal.away;
if (homeGoal == null) homeGoal = 0;
if (awayGoal == null) awayGoal = 0;
return Container(
margin: EdgeInsets.symmetric(vertical: 12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: Text(
match.home.name,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
Image.network(
match.home.logoUrl,
width: 36.0,
),
Expanded(
child: Text(
"${homeGoal} - ${awayGoal}",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
Image.network(
match.away.logoUrl,
width: 36.0,
),
Expanded(
child: Text(
match.away.name,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
],
),
);
}
And we have finished, try to run the app and see your beautiful application alive. if you liked this project don't forget to share it and you can tell us what you want to see for the next post
Make a Football Scoreboard App with Flutter
Reviewed by Medics
on
September 24, 2020
Rating:
i was able to run the app and the api json was printed in the console but the circular progress indicator kept on running why?
ReplyDeleteThe same to me ... it stops on
ReplyDeleteList matches = matchesList
.map((dynamic item) => SoccerMatch.fromJson(item))
.toList();
It doesn't go further
not working . i get this error== RangeError (index): Invalid value: Valid value range is empty: 0
ReplyDeletePlease check if u are properly get your api key, and typed address correctly and headers also. I recommend installing postman to check on this stuff first before typing code.
Deletethe app is working but only the first match shows time elapsed, how about the rest
ReplyDeleteSir where we found next part of this series .its paid or not working start yet.please answered this question...Thanks
ReplyDeleteteamstat.dart is missing can you please add it?
ReplyDeleteNot working time waste
ReplyDeleteteamstat.dart is missing please add this tutorial
ReplyDeleteGet Postal Code
ReplyDeletecovid 19 test in pitampura
ReplyDeletehi
ReplyDeletegetAllMatches()
is error. How to solve?
how did you solve it?
Deletei need this answer too
DeleteHi,
ReplyDeleteThis file is missing: teamstat.dart';
Voetbal Bookmaker
ReplyDelete