I have created a function in my app which makes a custom widget according to my need. Here is the code for the function
Widget customCircularButton(
{String title, String subTitle, String img, void Function() onTap}) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: onTap,
child: CircleAvatar(
radius: screenWidth(context) / 6,
backgroundColor: pColor,
child: CircleAvatar(
radius: screenWidth(context) / 6 - 2,
backgroundColor: Colors.white,
backgroundImage: Image.asset(img).image,
),
),
),
Container(
margin: EdgeInsets.all(5),
child: Text(
title,
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20),
),
),
Container(
margin: EdgeInsets.all(5),
width: screenWidth(context) / 3,
child: Text(
subTitle,
style: TextStyle(fontWeight: FontWeight.w300, fontSize: 12),
textAlign: TextAlign.center,
))
],
);
}
So to call this function into my widget i call it like this
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
customCircularButton(
title: 'Donate',
subTitle: 'Donate/Buy food for needy',
img: 'assets/images/donate-food.png',
onTap: donateDiaolg,
),
customCircularButton(
title: 'Become Volunteer',
subTitle: 'Distribute food to the needy',
img: 'assets/images/become-volunteer.png',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BecomeVolunteer()));
}),
],
),
Here donateDialog is another function which opens up a dialog.
void donateDiaolg() {
showDialog(..implementation..);}
So my doubt here is that should is use fat operator to call the donateDialog function or just call it like there in above code.
My basic question is should i use this
onTap: () => donateDialog(),
or this
onTap: donateDialog(),
or is it okay to do like this
onTap: donateDialog
It would be better if someone explains me these three function call.
It depends on function signature. for example onTap property needs function with no argument. if your custom function is same you can use your function name directly like onTap: myFunc. if your function's signature take 1 or more arguments you should pass empty function to onTap and call your function through it.
Hello good day everyone i want to make my listview into a expanded listview i pull my data using mysql
i want to display first the transaction id and the vesselname then in the side it has it mut have a arrow that when you click it it will show other information details.
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: getData,
key: _refresh,
child: loading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: list.length,
itemBuilder: (context, i) {
final x = list[i];
debugPrint(x.toString());
return Container(
padding: EdgeInsets.all(20.0),
child: Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
the data will be shown first is transaction id and vessel name a arrow icon on the side when it is click it will show the other information
Text(
'Transaction ID:\t' + x.transaction_id,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
Text('Vessel Name:\t' + x.vesselname,
style: TextStyle(fontSize: 20.0)),
//this will be the the information displayed after the side arrow will be click
Text('Type of Port :\t' + x.typeofport.capitalize(),
style: TextStyle(fontSize: 20.0)),
Text('Vessel Number:\t' + x.voyageno,
style: TextStyle(fontSize: 20.0)),
Text('Ship Call #:\t' + x.scn,
style: TextStyle(fontSize: 20.0)),
Text('OR #:\t' + x.ornum,
style: TextStyle(fontSize: 20.0)),
Text(
'Amount:\t ' +
money.format(int.parse(x.payment)),
style: TextStyle(fontSize: 20.0)),
Text('Status:\t' + x.status.toUpperCase(),
style: TextStyle(
fontSize: 25.0,
fontWeight: FontWeight.bold,
color: x.status == 'pending'
? Colors.red
: Colors.green)),
Divider()
],
),
),
],
),
);
},
),
));
}
}
first when you fetch data in your DTO you can put bool variable inside or you can remap your DTO and put variable bool
so your variable inside somehow like this:
Map<DTO, bool>
or
DTO{
........, bool collapsed;
}
then in your code when you create your builder
final x = list[i]; >> changed to entries if you used Map [final x = mapData[i].entries.toList()]
return Container(
padding: EdgeInsets.all(20.0),
child: GestureDetector(
onTap: (){
setState({
// if you using Map
x[i] = !x.value;
// if you using DTO
x.collapsed = !x.collapsed;
});
},
child: Column(
children:[
// Your Header
Row(
children: <Widget>[
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
the data will be shown first is transaction id and vessel name a arrow icon on the side when it is click it will show the other information
Text(
'Transaction ID:\t' + x.transaction_id,
style: TextStyle(
fontSize: 20.0, fontWeight: FontWeight.bold),
),
Text('Vessel Name:\t' + x.vesselname,
style: TextStyle(fontSize: 20.0)),
]
// Your Detail
// [if you used DTO]
if(!x.collapsed) Container(child:.......)
// [if you used Map]
if(!x.value) Container(child:......)
)
)
this is only the logic of changing the list inside to become Collapsible listView
explore ExpansionTile in flutter, I think it fits your requirement.
I am currently using the google_maps_flutter package, and I am placing it within a stack and overlaying it with a button. When the button is pressed, an alert should pop up.
The problem I am currently having is that it works upon first load, but if I exit the app, putting it in the background, and I reenter the app, the alertDialog is no longer showing up. It exists on the screen because I am unable to move the map, and I have to click the area where the button would normally be, but it is not visible.
Any ideas on what's going on?
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Stack(
children: <Widget>[
new Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: new Opacity(
opacity: opacity,
child: new GoogleMap(
onMapCreated: initializeMap,
options: GoogleMapOptions(
//trackCameraPosition: true,
compassEnabled: true,
myLocationEnabled: true,
),
),
),
),
new Align(
alignment: new Alignment(0, 1),
child: new GestureDetector(
onTap: () {
alert();
},
child: new Image.asset(
'assets/test.png',
height: 150.0,
fit: BoxFit.cover,
),
),
),
],
),
),
),
}
alert() {
return showCupertinoDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog(
title: new Text("hello"),
content: new Text("hello"),
actions: <Widget>[
CupertinoDialogAction(
isDefaultAction: true,
child: Text("Ok"),
onPressed: () {
Navigator.pop(context);
}
),
CupertinoDialogAction(
child: Text("Cancel"),
onPressed: () {
Navigator.pop(context);
}
)
],
);
},
);
}
Keep in mind google_maps_flutter is a developer preview at version 0.0.3. Give it some time!
I'm currently creating an application that tracks general crypto data, along with this data we also post news articles tailored to crypto enthusiasts. Every aspect of this news article data is stored in string form, from image url to date published - full list below.
I'm looking for a way to save this data to the user's device. In a perfect situation I'd just have this data saved in a JSON array, but apart from not knowing how to perform this, I'm not sure if it's the most efficient way to save this data for later display.
If you decide that JSON would be the best way of saving this data, all I need to know is how to properly manage this data into an array of different saved articles and how to import this properly into my Dart code.
An example of this code would be great, I'm looking to publish this app before the new year so I need all the help I can get. Many thanks.
This is the aforementioned data I'm looking to save / display from this source:
Source - source
Author - author
Description - description
Date Published - publishedAt
Article Title - title
Url to Article - url
Article Image - urlToImage
Edit: Trying to rework shadowsheep's answer to fit an index model
Each news widget is a new inkwell that allows a new scaffold to be built. From this scaffold you are presented with the option to save the article. On saving, the code currently just changes the value of the following strings with the title, description, URL and Image URL.
_sTitle
_sDescription
_sURL
_sURLtoImage
I would really like a way of having the database, as described by shadowsheep, saved to the user's device. This means that the saved articles will become persistent on the device despite the user closing and opening the app.
The following code is the exact use case in which I'm displaying my news data.
CarouselSlider(
items: [1,2,3,4,5,6,7,8,9,10].map((index) {
return Builder(
builder: (BuildContext context) {
return Padding(
padding: EdgeInsets.only(
top: 5.0,
bottom: 20.0,
),
child: InkWell(
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(15.0),
topRight: const Radius.circular(15.0),
),
onTap: () {
print('Opened article scaffold: "' + articles[index].title + "\"");
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
backgroundColor: const Color(0xFF273A48),
elevation: 0.0,
title: Container(
width: _width*0.90,
height: 30,
padding: const EdgeInsets.only(
bottom: 5,
top: 5,
left: 10,
right: 10,
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
alignment: Alignment.center,
child: AutoSizeText(
'Published ' + DateFormat.yMMMd().format(DateTime.parse(articles[index].publishedAt)) + ", "+ DateFormat.jm().format(DateTime.parse(articles[index].publishedAt)),
overflow: TextOverflow.ellipsis,
maxLines: 1,
minFontSize: 5,
maxFontSize: 20,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontFamily: 'Poppins',
),
),
),
),
body: Center(
child: Scaffold(
resizeToAvoidBottomPadding: false,
body: Center(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
const Color(0xFF273A48),
Colors.blueGrey
],
),
),
padding: const EdgeInsets.only(
top: 20,
left: 10,
right: 10,
bottom: 50
),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
FutureBuilder<Null>(future: _launched, builder: _launchStatus),
AutoSizeText(
articles[index].title,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
maxFontSize: 30,
minFontSize: 15,
maxLines: 3,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
Divider(
color: Colors.transparent,
height: 15.0,
),
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
color: Colors.transparent,
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(70),
blurRadius: 50.0,
)
],
image: DecorationImage(
image: NetworkImage(articles[index].urlToImage),
fit: BoxFit.fitHeight,
),
),
height: 220,
width: 317.5,
),
Divider(
color: Colors.transparent,
height: 15.0,
),
],
),
Container(
padding: const EdgeInsets.only(
left: 20,
right: 20
),
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
child: AutoSizeText(
articles[index].description,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
maxFontSize: 30,
minFontSize: 10,
maxLines: 10,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
width: _width*0.90,
height: _height*0.20,
),
Container(
padding: const EdgeInsets.all(4.0),
decoration: BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
IconButton(
icon: Icon(
Icons.favorite_border,
color: Colors.red
),
iconSize: 35.0,
onPressed: () {
_sTitle = articles[index].title;
_sDescription = articles[index].description;
_sURL = articles[index].url;
_sURLtoImage = articles[index].urlToImage;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => _favoritesScreen())
);
}
),
IconButton(
icon: Icon(
Icons.mobile_screen_share,
color: Colors.white,
),
iconSize: 35.0,
onPressed: () {
Share.share(
articles[index].title + "\n\nCheck out this article at:\n" + articles[index].url + "\n\nLearn more with Cryp - Tick Exchange",
);
}
),
IconButton(
icon: Icon(Icons.launch, color: Colors.lightBlueAccent),
iconSize: 32.5,
onPressed: () => setState(() { _launched = _launchInWebViewOrVC(articles[index].url);}),
),
],
),
),
],
),
),
),
),
),
)
)
);
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: const Color(0xFF273A48),
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(70),
offset: const Offset(5.0, 5.0),
blurRadius: 12.5,
)
],
image: DecorationImage(
alignment: Alignment.topCenter,
image: NetworkImage(articles[index].urlToImage),
fit: BoxFit.cover,
),
),
height: _height*0.35,
width: _width*0.725,
child: Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 10.0, right: 10.0),
decoration: BoxDecoration(
color: const Color(0xFF273A48),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(10.0),
bottomRight: Radius.circular(10.0)
),
),
height: 60.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
child: Container(
width: _width*0.725,
child: Text(
articles[index].title,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
maxLines: 2,
style: TextStyle(
color: Colors.white,
fontFamily: 'Poppins',
),
),
),
),
Text(
'Published ' + DateFormat.yMMMd().format(DateTime.parse(articles[index].publishedAt)) + ", "+ DateFormat.jm().format(DateTime.parse(articles[index].publishedAt)),
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: Colors.blueGrey,
fontSize: 10.0,
fontFamily: 'Poppins',
),
),
],
)
),
Container(
width: 25.0,
height: 20.0,
alignment: Alignment.center,
child: Text(
"$index",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.blueGrey,
fontSize: 10.0,
fontFamily: "Poppins"
),
)
),
],
),
)
],
),
),
),
);
},
);
}).toList(),
height: 400,
autoPlay: true,
)
If you want to save data in a persitance way in Dart code and be able to use it on Android and iOS I suggest you an sqlite plugin like that:
https://github.com/tekartik/sqflite
Otherwise if you only need to save a bunch of data use the shared_preferences plugin
https://github.com/flutter/plugins/tree/master/packages/shared_preferences
These two plugins both support either Android and iOS
You are requesting a lot of code ^_^ (ain't it).
So first of all you need to get your json through an HTTP call. For that use the http flutter package:
const request = "https://newsapi.org/v2/top-headlines?sources=crypto-coins-news&apiKey=d40a757cfb2e4dd99fc511a0cbf59098";
http.Response response = await http.get(request);
debugPrint("Response: " + response.body);
Wrap it up in an async method:
void _jsonAndSqlite() async {
...
}
And in the response variable you have your full JSON.
Now you need to serialize and I suggest you this really good reading.
I've choose for this answer the Manaul JSON Decoding
Manual JSON decoding refers to using the built-in JSON decoder in
dart:convert. It involves passing the raw JSON string to the
json.decode() method, and then looking up the values you need in the
Map the method returns. It has no external
dependencies or particular setup process, and it’s good for a quick
proof of concept.
var myBigJSONObject = json.decode(response.body);
var status = myBigJSONObject['status'];
var totalResults = myBigJSONObject['totalResults'];
var myArticles = myBigJSONObject['articles'];
debugPrint("articles: " + myArticles.toString());
Now that we have articles will try to save them on Sqlite DB through Sqflite package
var myFirstArticle = myArticles[0];
var author = myFirstArticle['author'];
var title = myFirstArticle['title'];
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'test.db');
// Delete the database
await deleteDatabase(path);
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, author TEXT, title TEXT)');
});
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Article(author, title) VALUES("$author", "$title")');
debugPrint('inserted1: $id1');
});
And that's it! Have fun studing and coding. Read the articles I've posted for you for JSON serailization and play around with my code, and trying to adding some other best practices they may better fit your needs. This is just a quick playground to, well, play with.
So I ended up with this method:
[...]
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
[...]
void _jsonAndSqlite() async {
const request =
"https://newsapi.org/v2/top-headlines?sources=crypto-coins-news&apiKey=d40a757cfb2e4dd99fc511a0cbf59098";
http.Response response = await http.get(request);
debugPrint("Response: " + response.body);
var myBigJSONObject = json.decode(response.body);
var status = myBigJSONObject['status'];
var totalResults = myBigJSONObject['totalResults'];
var myArticles = myBigJSONObject['articles'];
debugPrint("articles: " + myArticles.toString());
var myFirstArticle = myArticles[0];
var author = myFirstArticle['author'];
var title = myFirstArticle['title'];
// Get a location using getDatabasesPath
var databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'test.db');
// Delete the database
await deleteDatabase(path);
// open the database
Database database = await openDatabase(path, version: 1,
onCreate: (Database db, int version) async {
// When creating the db, create the table
await db.execute(
'CREATE TABLE Article (id INTEGER PRIMARY KEY, author TEXT, title TEXT)');
});
// Insert some records in a transaction
await database.transaction((txn) async {
int id1 = await txn.rawInsert(
'INSERT INTO Article(author, title) VALUES("$author", "$title")');
debugPrint('inserted1: $id1');
});
}
I have a screen with multiples json request, but it is loading all in the same time, i want to when finish one start the another until the end.
new CustomScrollView(
cacheExtent: height * 5,
slivers: [
new SliverList(
delegate: new SliverChildListDelegate(
[
new RelatorioVendPeriodoAPeriodo(),
new RelatorioDiasDaSemanas(),
new RelatorioVendasTotalidasPorPeriodo(),
new RelatorioDasVendasTotsProdutos(),
new RelatorioMensals(),
]
)
)
]
),
this classes loads a json request, how to divide and await one to start other?
Here one of this classes return method:
Widget build(BuildContext context) {
double height = (MediaQuery.of(context).size.height) - kRadialReactionRadius - kToolbarHeight;
return new Container(
height: height,
padding: new EdgeInsets.only(left: 5.0, right: 5.0),
child: new Card(
elevation: 10.0,
child:
new Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Column(crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new ListTile(
trailing:
_buildCounterButton(),
title: new Center(child: new Text('FATURAMENTO MENSAL', style: new TextStyle(fontWeight: FontWeight.bold))),
subtitle: new Icon(Icons.info),
onTap: _showDialog,
),
new FutureBuilder<List<RelatorioMensal>>(
future: fetchRelatorioMensal(new http.Client(), "", '$dateFinal1Sem'),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? new porVendaMensal(listVendasMensais: snapshot.data,)
: new Center(child: new CircularProgressIndicator());
}
),
],),]
),
),
);
}