mirror of
https://github.com/nisrulz/flutter-examples.git
synced 2025-11-08 12:39:17 +00:00
Added covid-19 example app and Updated the readme (#73)
This commit is contained in:
19
covid19_mobile_app/lib/main.dart
Normal file
19
covid19_mobile_app/lib/main.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'screens/home.dart';
|
||||
|
||||
void main() => runApp(MyApp());
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Covid-19',
|
||||
theme: ThemeData(
|
||||
primarySwatch: Colors.blue,
|
||||
accentColor: Color(0xfff4796b),
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
home: Home(),
|
||||
);
|
||||
}
|
||||
}
|
||||
56
covid19_mobile_app/lib/resources/fetch_data_functions.dart
Normal file
56
covid19_mobile_app/lib/resources/fetch_data_functions.dart
Normal file
@@ -0,0 +1,56 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
// function to fetch global Corona Virus(all countries together)
|
||||
// to fetch data of a particular country(in this case, India)
|
||||
Future getAllData() async {
|
||||
try {
|
||||
var allCountriesUrl = 'https://corona.lmao.ninja/v2/all';
|
||||
var allCountriesResponse = await http.get(allCountriesUrl);
|
||||
|
||||
var particularCountryUrl = 'https://corona.lmao.ninja/v2/historical/India';
|
||||
var particularCountryResponse = await http.get(particularCountryUrl);
|
||||
|
||||
// a list to store the data points
|
||||
List<Map<String, dynamic>> dataPoints = [];
|
||||
jsonDecode(particularCountryResponse.body)['timeline']['cases']
|
||||
.forEach((k, v) {
|
||||
List a = k.split('/');
|
||||
DateTime b = DateTime(int.parse(a[2]), int.parse(a[0]), int.parse(a[1]));
|
||||
dataPoints.add({"date": b, "value": v});
|
||||
});
|
||||
List<Map<String, dynamic>> dataPoints1 = [];
|
||||
jsonDecode(particularCountryResponse.body)['timeline']['deaths']
|
||||
.forEach((k, v) {
|
||||
List a = k.split('/');
|
||||
DateTime b = DateTime(int.parse(a[2]), int.parse(a[0]), int.parse(a[1]));
|
||||
dataPoints1.add({"date": b, "value": v});
|
||||
});
|
||||
List<Map<String, dynamic>> dataPoints2 = [];
|
||||
jsonDecode(particularCountryResponse.body)['timeline']['recovered']
|
||||
.forEach((k, v) {
|
||||
List a = k.split('/');
|
||||
DateTime b = DateTime(int.parse(a[2]), int.parse(a[0]), int.parse(a[1]));
|
||||
dataPoints2.add({"date": b, "value": v});
|
||||
});
|
||||
return {
|
||||
"all": allCountriesResponse.body,
|
||||
"country": dataPoints,
|
||||
"deaths": dataPoints1,
|
||||
"recovered": dataPoints2
|
||||
};
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
|
||||
// function to fetch data of all countries(country wise)
|
||||
Future getAllCountriesData() async {
|
||||
try {
|
||||
var url = 'https://corona.lmao.ninja/v2/countries?sort=country';
|
||||
var response = await http.get(url);
|
||||
return response.body;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
}
|
||||
}
|
||||
94
covid19_mobile_app/lib/screens/countrylist.dart
Normal file
94
covid19_mobile_app/lib/screens/countrylist.dart
Normal file
@@ -0,0 +1,94 @@
|
||||
import 'package:covid19_mobile_app/resources/fetch_data_functions.dart';
|
||||
import 'package:covid19_mobile_app/widgets/foldable_cell_widgets.dart';
|
||||
|
||||
import '../screens/searchCountry.dart';
|
||||
import '../widgets/drawer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:folding_cell/folding_cell.dart';
|
||||
|
||||
class CountryList extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<dynamic> results;
|
||||
return Scaffold(
|
||||
drawer: DrawerWidget(),
|
||||
appBar: AppBar(
|
||||
title: Text("Affected Countries"),
|
||||
centerTitle: true,
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: Icon(Icons.search),
|
||||
onPressed: () {
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: CountrySearchDelegate(results),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: getAllCountriesData(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting)
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
if (snapshot.hasError)
|
||||
return Center(
|
||||
child: Text("Error! please check you wifi connection"),
|
||||
);
|
||||
results = jsonDecode(snapshot.data);
|
||||
return ListView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemCount: results.length,
|
||||
itemBuilder: (context, index) {
|
||||
var _foldingCellKey = GlobalKey<SimpleFoldingCellState>();
|
||||
return Container(
|
||||
color: Color(0xFF2e282a),
|
||||
alignment: Alignment.topCenter,
|
||||
child: SimpleFoldingCell(
|
||||
key: _foldingCellKey,
|
||||
frontWidget: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
SimpleFoldingCellState foldingCellState =
|
||||
context.findAncestorStateOfType();
|
||||
foldingCellState?.toggleFold();
|
||||
},
|
||||
child: Container(
|
||||
color: Color(0xff000000),
|
||||
child: buildFrontWidget(
|
||||
context,
|
||||
results[index]['countryInfo']['flag'],
|
||||
results[index]['country'],
|
||||
results[index]['cases'].toString())),
|
||||
);
|
||||
},
|
||||
),
|
||||
innerTopWidget: buildInnerTopWidget(
|
||||
results[index]['country'],
|
||||
results[index]['todayCases'].toString(),
|
||||
results[index]['deaths'].toString(),
|
||||
results[index]['todayDeaths'].toString(),
|
||||
results[index]['recovered'].toString(),
|
||||
results[index]['critical'].toString(),
|
||||
results[index]['casesPerOneMillion'].toString(),
|
||||
),
|
||||
innerBottomWidget: buildInnerBottomWidget(
|
||||
results[index]['cases'].toString()),
|
||||
cellSize: Size(MediaQuery.of(context).size.width, 125),
|
||||
padding: EdgeInsets.all(15),
|
||||
animationDuration: Duration(milliseconds: 300),
|
||||
borderRadius: 10,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
138
covid19_mobile_app/lib/screens/home.dart
Normal file
138
covid19_mobile_app/lib/screens/home.dart
Normal file
@@ -0,0 +1,138 @@
|
||||
import 'dart:convert';
|
||||
import 'package:covid19_mobile_app/resources/fetch_data_functions.dart';
|
||||
import 'package:covid19_mobile_app/widgets/graph.dart';
|
||||
import 'package:covid19_mobile_app/widgets/info_card.dart';
|
||||
import '../widgets/drawer.dart';
|
||||
import 'package:number_display/number_display.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
final refreshKey = GlobalKey<RefreshIndicatorState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
drawer: DrawerWidget(),
|
||||
appBar: AppBar(
|
||||
title: Text(
|
||||
"World Wide Cases",
|
||||
),
|
||||
centerTitle: true,
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
// pull to refresh
|
||||
key: refreshKey,
|
||||
onRefresh: () => Navigator.pushReplacement(context,
|
||||
PageRouteBuilder(pageBuilder: (context, a1, a2) => Home())),
|
||||
child: FutureBuilder(
|
||||
future: getAllData(),
|
||||
builder: (context, snapshot) {
|
||||
// Display CircularProgressIndicator if data isn't fetched yet
|
||||
if (snapshot.connectionState == ConnectionState.waiting)
|
||||
return Center(child: CircularProgressIndicator());
|
||||
// If in case an error occurs
|
||||
if (snapshot.hasError) {
|
||||
return Container(
|
||||
child: Center(
|
||||
child: Text(
|
||||
"Failed to load data. Please check you wifi connection!",
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// results of all countries(taken together)
|
||||
Map<String, dynamic> globalResults =
|
||||
json.decode(snapshot.data['all']);
|
||||
|
||||
// daily cases results
|
||||
List<Map<String, dynamic>> dailyCasesResults =
|
||||
(snapshot.data['country']);
|
||||
|
||||
// daily deaths results
|
||||
List<Map<String, dynamic>> dailyDeaths =
|
||||
(snapshot.data['deaths']);
|
||||
|
||||
// daily recoveries results
|
||||
List<Map<String, dynamic>> dailyRecoveries =
|
||||
(snapshot.data['recovered']);
|
||||
|
||||
// To display data in a width-limited component
|
||||
// Eg: converts 2,000,000 to 2M
|
||||
final updateNumberDisplay = createDisplay(length: 4);
|
||||
|
||||
return Padding(
|
||||
padding:
|
||||
EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
|
||||
child: ListView(
|
||||
physics: BouncingScrollPhysics(),
|
||||
children: <Widget>[
|
||||
GridView.count(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
crossAxisCount: 2,
|
||||
children: <Widget>[
|
||||
infoCard(context, "Total Cases",
|
||||
globalResults['cases'].toString()),
|
||||
infoCard(context, "Deaths",
|
||||
globalResults['deaths'].toString()),
|
||||
infoCard(context, "Recovered",
|
||||
globalResults['recovered'].toString()),
|
||||
infoCard(context, "Active",
|
||||
globalResults['active'].toString()),
|
||||
infoCard(context, "Updated",
|
||||
updateNumberDisplay(globalResults['updated'])),
|
||||
infoCard(context, "Affected Countries",
|
||||
globalResults['affectedCountries'].toString()),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
height: 25.0,
|
||||
),
|
||||
Text(
|
||||
"Daily Cases in India",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: MediaQuery.of(context).size.height * 0.03,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
buildGraph(context, dailyCasesResults),
|
||||
SizedBox(
|
||||
height: 25.0,
|
||||
),
|
||||
Text(
|
||||
"Daily Deaths in India",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: MediaQuery.of(context).size.height * 0.03,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
buildGraph(context, dailyDeaths),
|
||||
SizedBox(
|
||||
height: 25.0,
|
||||
),
|
||||
Text(
|
||||
"Daily Recoveries in India",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: MediaQuery.of(context).size.height * 0.03,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
buildGraph(context, dailyRecoveries),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
));
|
||||
}
|
||||
}
|
||||
165
covid19_mobile_app/lib/screens/searchCountry.dart
Normal file
165
covid19_mobile_app/lib/screens/searchCountry.dart
Normal file
@@ -0,0 +1,165 @@
|
||||
import 'package:covid19_mobile_app/widgets/foldable_cell_widgets.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:folding_cell/folding_cell.dart';
|
||||
|
||||
class CountrySearchDelegate extends SearchDelegate {
|
||||
List<dynamic> results;
|
||||
CountrySearchDelegate(this.results);
|
||||
|
||||
// to put the 'Clear Icon(X)' in the traling part of the search text field
|
||||
// to clear the contents of the text field
|
||||
@override
|
||||
List<Widget> buildActions(BuildContext context) {
|
||||
return [
|
||||
IconButton(
|
||||
icon: Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
query = '';
|
||||
},
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
// to put the 'Back icon(<-)' in the leading part of the search text field
|
||||
// to go back
|
||||
@override
|
||||
Widget buildLeading(BuildContext context) {
|
||||
return IconButton(
|
||||
icon: Icon(Icons.arrow_back),
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// to build results according to the query
|
||||
// it is when the user types something and presses enter
|
||||
@override
|
||||
Widget buildResults(BuildContext context) {
|
||||
final suggestionsList = results
|
||||
.where((element) => element['country']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(query.toLowerCase()))
|
||||
.toList();
|
||||
return ListView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemCount: suggestionsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
var _foldingCellKey = GlobalKey<SimpleFoldingCellState>();
|
||||
return Container(
|
||||
color: Color(0xFF2e282a),
|
||||
alignment: Alignment.topCenter,
|
||||
child: SimpleFoldingCell(
|
||||
key: _foldingCellKey,
|
||||
frontWidget: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
SimpleFoldingCellState foldingCellState =
|
||||
context.findAncestorStateOfType();
|
||||
foldingCellState?.toggleFold();
|
||||
},
|
||||
child: Container(
|
||||
color: Color(0xff000000),
|
||||
child: buildFrontWidget(
|
||||
context,
|
||||
suggestionsList[index]['countryInfo']['flag'],
|
||||
suggestionsList[index]['country'],
|
||||
suggestionsList[index]['cases'].toString())),
|
||||
);
|
||||
},
|
||||
),
|
||||
innerTopWidget: buildInnerTopWidget(
|
||||
suggestionsList[index]['country'],
|
||||
suggestionsList[index]['todayCases'].toString(),
|
||||
suggestionsList[index]['deaths'].toString(),
|
||||
suggestionsList[index]['todayDeaths'].toString(),
|
||||
suggestionsList[index]['recovered'].toString(),
|
||||
suggestionsList[index]['critical'].toString(),
|
||||
suggestionsList[index]['casesPerOneMillion'].toString(),
|
||||
),
|
||||
innerBottomWidget: buildInnerBottomWidget(
|
||||
suggestionsList[index]['cases'].toString()),
|
||||
cellSize: Size(MediaQuery.of(context).size.width, 125),
|
||||
padding: EdgeInsets.all(15),
|
||||
animationDuration: Duration(milliseconds: 300),
|
||||
borderRadius: 10,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// to set a placeholder for the search text field
|
||||
@override
|
||||
String get searchFieldLabel => 'Search Country';
|
||||
|
||||
// to set the theme for search bar
|
||||
@override
|
||||
ThemeData appBarTheme(BuildContext context) {
|
||||
return ThemeData(
|
||||
primaryColor: Colors.black,
|
||||
textTheme: Theme.of(context).textTheme.apply(),
|
||||
);
|
||||
}
|
||||
|
||||
// to build suggestions according to the query
|
||||
// it is when the user types something but does not press enter
|
||||
@override
|
||||
Widget buildSuggestions(BuildContext context) {
|
||||
final suggestionsList = results
|
||||
.where((element) => element['country']
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.contains(query.toLowerCase()))
|
||||
.toList();
|
||||
return ListView.builder(
|
||||
physics: BouncingScrollPhysics(),
|
||||
itemCount: suggestionsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
var _foldingCellKey = GlobalKey<SimpleFoldingCellState>();
|
||||
return Container(
|
||||
color: Color(0xFF2e282a),
|
||||
alignment: Alignment.topCenter,
|
||||
child: SimpleFoldingCell(
|
||||
key: _foldingCellKey,
|
||||
frontWidget: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
SimpleFoldingCellState foldingCellState =
|
||||
context.findAncestorStateOfType();
|
||||
foldingCellState?.toggleFold();
|
||||
},
|
||||
child: Container(
|
||||
color: Color(0xff000000),
|
||||
child: buildFrontWidget(
|
||||
context,
|
||||
suggestionsList[index]['countryInfo']['flag'],
|
||||
suggestionsList[index]['country'],
|
||||
suggestionsList[index]['cases'].toString())),
|
||||
);
|
||||
},
|
||||
),
|
||||
innerTopWidget: buildInnerTopWidget(
|
||||
suggestionsList[index]['country'],
|
||||
suggestionsList[index]['todayCases'].toString(),
|
||||
suggestionsList[index]['deaths'].toString(),
|
||||
suggestionsList[index]['todayDeaths'].toString(),
|
||||
suggestionsList[index]['recovered'].toString(),
|
||||
suggestionsList[index]['critical'].toString(),
|
||||
suggestionsList[index]['casesPerOneMillion'].toString(),
|
||||
),
|
||||
innerBottomWidget: buildInnerBottomWidget(
|
||||
suggestionsList[index]['cases'].toString()),
|
||||
cellSize: Size(MediaQuery.of(context).size.width, 125),
|
||||
padding: EdgeInsets.all(15),
|
||||
animationDuration: Duration(milliseconds: 300),
|
||||
borderRadius: 10,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
40
covid19_mobile_app/lib/widgets/drawer.dart
Normal file
40
covid19_mobile_app/lib/widgets/drawer.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import '../screens/home.dart';
|
||||
import '../screens/countrylist.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DrawerWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Drawer(
|
||||
child: ListView(
|
||||
// Important: Remove any padding from the ListView.
|
||||
padding: EdgeInsets.zero,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Image.asset('assets/virus.gif'),
|
||||
),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
child: Image.asset("assets/logo.png"),
|
||||
),
|
||||
title: Text('Home'),
|
||||
onTap: () {
|
||||
Navigator.pushReplacement(
|
||||
context, MaterialPageRoute(builder: (context) => Home()));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
child: Image.asset("assets/logo.png"),
|
||||
),
|
||||
title: Text('Affected Countries'),
|
||||
onTap: () {
|
||||
Navigator.pushReplacement(context,
|
||||
MaterialPageRoute(builder: (context) => CountryList()));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
143
covid19_mobile_app/lib/widgets/foldable_cell_widgets.dart
Normal file
143
covid19_mobile_app/lib/widgets/foldable_cell_widgets.dart
Normal file
@@ -0,0 +1,143 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:folding_cell/folding_cell.dart';
|
||||
import 'package:number_display/number_display.dart';
|
||||
|
||||
// To display data in a width-limited component
|
||||
// Eg: converts 2,000,000 to 2M
|
||||
String updateNumberDisplay(String number) {
|
||||
final display = createDisplay(length: 4);
|
||||
// we are converting number to an integer because it is a string
|
||||
// and display expects an integer
|
||||
return display(int.parse(number));
|
||||
}
|
||||
|
||||
// the front widget for the foldable cell(when cell is collapsed)
|
||||
Widget buildFrontWidget(
|
||||
BuildContext context, String flagUrl, String country, String cases) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: Image.network(
|
||||
flagUrl,
|
||||
width: MediaQuery.of(context).size.width * 0.2,
|
||||
fit: BoxFit.cover,
|
||||
)),
|
||||
SizedBox(
|
||||
width: 20.0,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Country: $country",
|
||||
),
|
||||
Text("Total Cases: ${updateNumberDisplay(cases)}"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// the inner top widget for the foldable cell(when cell is expanded)
|
||||
Widget buildInnerTopWidget(String country, String todayCases, String deaths,
|
||||
String todayDeaths, String recovered, String critical, String cpm) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0),
|
||||
color: Color(0xfff44e3f),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
country,
|
||||
style: TextStyle(fontSize: 20.0),
|
||||
),
|
||||
SizedBox(
|
||||
height: 10.0,
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Today Cases: ${updateNumberDisplay(todayCases)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
Text(
|
||||
"Deaths: ${updateNumberDisplay(deaths)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
Text(
|
||||
"Cases/Million: ${updateNumberDisplay(cpm)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: 10.0,
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"Recovered: ${updateNumberDisplay(recovered)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
Text(
|
||||
"Today Deaths: ${updateNumberDisplay(todayDeaths)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
Text(
|
||||
"Critical: ${updateNumberDisplay(critical)}",
|
||||
style: TextStyle(fontSize: 18.0),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// the inner bottom widget for the foldable cell(when cell is expanded)
|
||||
Widget buildInnerBottomWidget(String cases) {
|
||||
return Builder(builder: (context) {
|
||||
return Container(
|
||||
color: Color(0xfff44e3f),
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: Text(
|
||||
"Total Cases:\n${updateNumberDisplay(cases)}",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.0,
|
||||
),
|
||||
)),
|
||||
FlatButton(
|
||||
onPressed: () {
|
||||
SimpleFoldingCellState foldingCellState =
|
||||
context.findAncestorStateOfType();
|
||||
foldingCellState?.toggleFold();
|
||||
},
|
||||
child: Text(
|
||||
"Close",
|
||||
),
|
||||
color: Colors.black,
|
||||
shape: StadiumBorder(),
|
||||
splashColor: Colors.white.withOpacity(0.5),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
51
covid19_mobile_app/lib/widgets/graph.dart
Normal file
51
covid19_mobile_app/lib/widgets/graph.dart
Normal file
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:bezier_chart/bezier_chart.dart';
|
||||
|
||||
// Widget that will build the graph
|
||||
Widget buildGraph(
|
||||
BuildContext context, List<Map<String, dynamic>> datesAndValues) {
|
||||
// Data is avalaible from a particular date and we are getting that here
|
||||
final fromDate = datesAndValues[0]['date'];
|
||||
|
||||
// Data is avalaible until a particular date and we are getting that here
|
||||
final toDate = datesAndValues.last['date'];
|
||||
|
||||
// Add dates and values corresponding to those dates
|
||||
// in a list
|
||||
List<DataPoint<DateTime>> dataPoints = [];
|
||||
for (final dateAndValue in datesAndValues) {
|
||||
dataPoints.add(DataPoint<DateTime>(
|
||||
value: double.parse(dateAndValue['value'].toString()),
|
||||
xAxis: dateAndValue['date']));
|
||||
}
|
||||
|
||||
return Center(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
),
|
||||
height: MediaQuery.of(context).size.height / 2,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: BezierChart(
|
||||
fromDate: fromDate,
|
||||
bezierChartScale: BezierChartScale.WEEKLY,
|
||||
toDate: toDate,
|
||||
selectedDate: toDate,
|
||||
series: [
|
||||
BezierLine(
|
||||
data: dataPoints,
|
||||
),
|
||||
],
|
||||
config: BezierChartConfig(
|
||||
physics: BouncingScrollPhysics(),
|
||||
verticalIndicatorStrokeWidth: 3.0,
|
||||
verticalIndicatorColor: Colors.black26,
|
||||
showVerticalIndicator: true,
|
||||
verticalIndicatorFixedPosition: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
footerHeight: 30.0,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
31
covid19_mobile_app/lib/widgets/info_card.dart
Normal file
31
covid19_mobile_app/lib/widgets/info_card.dart
Normal file
@@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
// this is the rounded rectangle card widget that appears on the homescreen
|
||||
Widget infoCard(BuildContext context, String title, String number) {
|
||||
return Card(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: MediaQuery.of(context).size.height * 0.03,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: 5.0,
|
||||
),
|
||||
Text(
|
||||
number,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 20.0,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40.0)),
|
||||
color: Color(0xfff44e3f),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user