I have list of latitude and longitude which I am storing them in database.I want those latitude and longitude to be represented in flutter map with markers.
My code for saving latitude and longitude using sqlite
homeScreen.dart
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => new _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Note> items = new List();
DatabaseHelper db = new DatabaseHelper();
LatLng _center ;
Position currentLocation;
MapController _mapctl = MapController();
Future<Position> locateUser() async {
try{
return await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
}on PlatformException catch(e){
currentLocation = null;
}
return currentLocation;
}
getUserLocation() async {
currentLocation = await locateUser();
setState(() {
_center = LatLng(currentLocation.latitude, currentLocation.longitude);
});
print('center $_center');
}
@override
void initState() {
super.initState();
getUserLocation();
db.getAllNotes().then((notes) {
setState(() {
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
@override
Widget build(BuildContext context){
var markers = <Marker>[
Marker(
width: 80.0,
height: 80.0,
point: LatLng(12.9716, 77.5946),
builder: (ctx) => Container(
child: Icon(Icons.location_on,color: Colors.green[700],size: 30,),
),
),
Marker(
width: 80.0,
height: 80.0,
point: LatLng(12.9716, 77.5946),
builder: (ctx) => Container(
child: Icon(Icons.location_on)
),
),
];
return Scaffold(
appBar: AppBar(
title: Text('Plants Watch'),
backgroundColor: Colors.green[700],
actions: <Widget>[
IconButton(
icon: Icon(Icons.person),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context)=>UserProfile()));
},
),
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () {
BlocProvider.of<AuthenticationBloc>(context).dispatch(
LoggedOut(),
);
},
)
],
),
body: Stack(
children: <Widget>[
new FlutterMap(
mapController: _mapctl,
options: new MapOptions(
center: new LatLng(12.9716, 77.5946),
maxZoom: 20.0,
),
layers: [
new TileLayerOptions(
urlTemplate: "https://api.tiles.mapbox.com/v4/"
"{id}/{z}/{x}/{y}@2x.png?access_token={accessToken}",
additionalOptions: {
'accessToken': 'accessToken',
'id': 'mapbox.streets',
},
),
MarkerLayerOptions(markers: markers)
],
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Align(
alignment: Alignment.bottomRight,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
backgroundColor: Colors.green[700],
child: Icon(Icons.my_location),
onPressed: () {
_mapctl.move(_center,16.0);
},
),
SizedBox(height: 16.0),
FloatingActionButton(
backgroundColor: Colors.green[700],
child: Icon(Icons.add),
heroTag: null,
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => NoteScreen(Note('', '', ''))));
},
),
],
)
),
),
],
)
);
}
}
Listview.dart
class ListViewNote extends StatefulWidget {
@override
State<StatefulWidget> createState() => new ListViewNoteState();
}
class ListViewNoteState extends State<ListViewNote> {
List<Note> items = new List();
DatabaseHelper db = new DatabaseHelper();
@override
void initState() {
super.initState();
db.getAllNotes().then((notes) {
setState(() {
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Plant List',
),
centerTitle: true,
actions: <Widget>[
IconButton(icon: Icon(Icons.search,
color: Colors.white,), onPressed: (){
showSearch(context: context,
delegate: DataSearch(this.items));
})
],
),
body: Center(
child: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.all(15.0),
itemBuilder: (context, position) {
return Dismissible(
background: stackBehindDismiss(),
key: ObjectKey(items[position]),
child: Card(
elevation: 2.0,
margin: new EdgeInsets.symmetric(horizontal: 0.0,vertical: 2.0),
child: Column(
children: <Widget>[
ListTile(
title: Text(
'${items[position].title}',
style: TextStyle(
fontSize: 22.0,
color: Colors.deepOrangeAccent,
),
),
subtitle: Text(
'${items[position].description}' + '' + '${items[position].location}',
style: new TextStyle(
fontSize: 18.0,
fontStyle: FontStyle.italic,
),
),
onTap: () => _navigateToNote(context, items[position]),
),
],
),
),
onDismissed: (dirction){
var item = items.elementAt(position);
_deleteNote(context, items[position], position);
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Item deleted"),
));
},
);
}
),
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.green[700],
child: Icon(Icons.add),
onPressed: () => _createNewNote(context),
),
);
}
void _deleteNote(BuildContext context, Note note, int position) async {
db.deleteNote(note.id).then((notes) {
setState(() {
items.removeAt(position);
});
});
}
void _navigateToNote(BuildContext context, Note note) async {
String result = await Navigator.push(
context,MaterialPageRoute(builder: (context) => NoteScreen(note)),
);
if (result == 'update') {
db.getAllNotes().then((notes) {
setState(() {
items.clear();
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
}
void _createNewNote(BuildContext context) async {
String result = await Navigator.push(
context,MaterialPageRoute(builder: (context) => NoteScreen(Note('', '', ''))),
);
if (result == 'save') {
db.getAllNotes().then((notes) {
setState(() {
items.clear();
notes.forEach((note) {
items.add(Note.fromMap(note));
});
});
});
}
}
stackBehindDismiss() {
return Container(
alignment: Alignment.centerRight,
padding: EdgeInsets.only(right: 20.0),
color: Colors.green[700],
child: Icon(
Icons.delete,
color: Colors.white,
),
);
}
}
class DataSearch extends SearchDelegate<Note> {
DatabaseHelper db = new DatabaseHelper();
List<Note> items = new List();
final List<Note> suggestion = new List();
// ListViewNoteState i = ListViewNoteState();
DataSearch(this.items);
@override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
@override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(icon: Icon(Icons.clear), onPressed: () {
query = '';
} )
];
}
@override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: (){
close(context, null);
},
);
}
@override
Widget buildResults(BuildContext context) {
return Text(query);
}
@override
Widget buildSuggestions(BuildContext context) {
final suggestion = query.isEmpty
? items
: items.where((target) => target.title.startsWith(query)).toList();
if(items.isEmpty)
{
print("Null");
}
// return Text('$suggestion');
return ListView.builder(
itemCount: suggestion.length,
itemBuilder: (context, position){
return new ListTile(
title: RichText(
text: TextSpan(
text: suggestion[position].title.substring(0,query.length),
style: TextStyle(
color: Colors.black,fontWeight: FontWeight.bold),
children: [
TextSpan(
text: suggestion[position].title.substring(query.length),
style: TextStyle(color: Colors.black54)
)
]
),
)
);
}
);
}
}
Below is my databse classes where i am creating dbHelper and class note for creating table
dbHelper.dart
class DatabaseHelper {
static final DatabaseHelper _instance = new DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
final String tableNote = 'noteTable';
final String columnId = 'id';
final String columnLocation = 'location';
final String columnTitle = 'title';
final String columnDescription = 'description';
static Database _db;
DatabaseHelper.internal();
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
initDb() async {
String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'notes.db');
// await deleteDatabase(path); // just for testing
var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}
void _onCreate(Database db, int newVersion) async {
await db.execute(
'CREATE TABLE $tableNote($columnId INTEGER PRIMARY KEY,$columnLocation TEXT, $columnTitle TEXT, $columnDescription TEXT)');
}
Future<int> saveNote(Note note) async {
var dbClient = await db;
var result = await dbClient.insert(tableNote, note.toMap());
// var result = await dbClient.rawInsert(
// 'INSERT INTO $tableNote ($columnTitle, $columnDescription) VALUES (\'${note.title}\', \'${note.description}\')');
return result;
}
Future<List> getAllNotes() async {
var dbClient = await db;
var result = await dbClient.query(tableNote, columns: [columnId, columnLocation , columnTitle, columnDescription]);
// var result = await dbClient.rawQuery('SELECT * FROM $tableNote');
return result.toList();
}
Future<int> getCount() async {
var dbClient = await db;
return Sqflite.firstIntValue(await dbClient.rawQuery('SELECT COUNT(*) FROM $tableNote'));
}
Future<Note> getNote(int id) async {
var dbClient = await db;
List<Map> result = await dbClient.query(tableNote,
columns: [columnId, columnLocation , columnTitle, columnDescription],
where: '$columnId = ?',
whereArgs: [id]);
// var result = await dbClient.rawQuery('SELECT * FROM $tableNote WHERE $columnId = $id');
if (result.length > 0) {
return new Note.fromMap(result.first);
}
return null;
}
Future<int> deleteNote(int id) async {
var dbClient = await db;
return await dbClient.delete(tableNote, where: '$columnId = ?', whereArgs: [id]);
// return await dbClient.rawDelete('DELETE FROM $tableNote WHERE $columnId = $id');
}
Future<int> updateNote(Note note) async {
var dbClient = await db;
return await dbClient.update(tableNote, note.toMap(), where: "$columnId = ?", whereArgs: [note.id]);
// return await dbClient.rawUpdate(
// 'UPDATE $tableNote SET $columnTitle = \'${note.title}\', $columnDescription = \'${note.description}\' WHERE $columnId = ${note.id}');
}
Future close() async {
var dbClient = await db;
return dbClient.close();
}
}
classNote.dart
class Note {
int _id;
String _location;
String _title;
String _description;
Note(this._location,this._title, this._description);
Note.map(dynamic obj) {
this._id = obj['id'];
this._location = obj['location'];
this._title = obj['title'];
this._description = obj['description'];
}
int get id => _id;
String get location => _location;
String get title => _title;
String get description => _description;
Map<String, dynamic> toMap() {
var map = new Map<String, dynamic>();
if (_id != null) {
map['id'] = _id;
}
map['location'] = _location;
map['title'] = _title;
map['description'] = _description;
return map;
}
Note.fromMap(Map<String, dynamic> map) {
this._id = map['id'];
this._location = map ['location'];
this._title = map['title'];
this._description = map['description'];
}
}
AddItem.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:latlong/latlong.dart';
import 'dbhelper.dart';
import 'package:geolocator/geolocator.dart';
class NoteScreen extends StatefulWidget {
final Note note;
NoteScreen(this.note);
@override
State<StatefulWidget> createState() => new _NoteScreenState();
}
class _NoteScreenState extends State<NoteScreen> {
DatabaseHelper db = new DatabaseHelper();
TextEditingController _titleController;
TextEditingController _descriptionController;
TextEditingController _locationController;
@override
void initState() {
super.initState();
getUserLocation();
_titleController = new TextEditingController(text: widget.note.title);
_descriptionController = new TextEditingController(text: widget.note.description);
_locationController = new TextEditingController(text: widget.note.location);
}
LatLng _center ;
Position currentLocation;
Future<Position> locateUser() async {
try{
return await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
}on PlatformException catch(e){
currentLocation = null;
}
return currentLocation;
}
getUserLocation() async {
currentLocation = await locateUser();
setState(() {
_center = LatLng(currentLocation.latitude, currentLocation.longitude);
_locationController.text = _center.toString();
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add Plant'),
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.view_list),
tooltip: 'Next choice',
onPressed: () {
navigateToPlantList();
},
),
]
),
body: Container(
margin: EdgeInsets.all(15.0),
alignment: Alignment.center,
child: Column(
children: <Widget>[
TextField(
controller: _locationController,
decoration: InputDecoration(
labelText: 'Current location',
),
),
Padding(padding: new EdgeInsets.all(5.0)),
TextField(
controller: _titleController,
decoration: InputDecoration(labelText: 'Title'),
),
Padding(padding: new EdgeInsets.all(5.0)),
TextField(
controller: _descriptionController,
decoration: InputDecoration(labelText: 'Description'),
),
Padding(padding: new EdgeInsets.all(5.0)),
RaisedButton(
child: (widget.note.id != null) ? Text('Update') : Text('Add'),
onPressed: () {
if (widget.note.id != null) {
db.updateNote(Note.fromMap({
'id': widget.note.id,
'location': _locationController.text,
'title': _titleController.text,
'description': _descriptionController.text
})).then((_) {
Navigator.pop(context, 'update');
});
}else {
db.saveNote(Note(_locationController.text,_titleController.text, _descriptionController.text)).then((_) {
Navigator.pop(context, 'save');
});
}
},
),
],
),
),
);
}
void navigateToPlantList() {
Navigator.push(context,
new MaterialPageRoute(builder: (context) => new ListViewNote()),);
}
}
Now using this I want to written marker in my home screen
First of all, you should store latitude and longitude as two separate real value columns. This simplifies further steps.
Then you need a list of markers which can be updated later as field in the class:
List<Marker> _markers = [];
To update the markers (e. g. from the database) a function is used:
void setMarkers() async {
var notes = await db.getAllNotes();
List<Marker> markers = notes.map((n) {
LatLng point = LatLng(n.latitude, n.longitude);
return Marker(
width: 80.0,
height: 80.0,
point: point,
builder: (ctx) => Container(
child: Icon(
Icons.location_on,
color: Colors.green[700],
size: 30,
),
),
);
}).toList();
setState(() {
_markers.clear();
_markers = markers;
});
}
This function fetches all Notes from the database and updates the Markers.
In the FlutterMap widget replace the list of markers with the _markers
field:
MarkerLayerOptions(markers: _markers)
To ensure, that all items are loaded shortly after the app started, call the setMarkers()
function in initState()
and to add a new Marker, which can be created in your NoteScreen widget, to the map replace the call from your FloatingActionButton of the HomeScreen with
onPressed: () async {
await Navigator.push(
context, MaterialPageRoute(builder: (context) => AddPlantScreen(Plant.empty())));
setMarkers();
},
This updates the map after a new entry was created.
Note: Clearing and fully reloading the data every time from the database is not the best way, but this is up to you to optimize.
You do get the current location separated:
void getCurrentPosition() async {
Position currentLocation = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
_center = LatLng(currentLocation.latitude, currentLocation.longitude);
});
}
What you need to do in order for that to work is update your Note class to support a double _latitude;
and double _longitude;
instead of String _location;
So you need to update the map functions, the getters and the constructor.
Furthermore, you need to adjust your DatabaseHelper class:
final String columnLatitude = 'latitude';
final String columnLongitude = 'longitude';
// new create table statement
'CREATE TABLE $tableNote($columnId INTEGER PRIMARY KEY, $columnLatitude REAL, $columnLongitude REAL, $columnTitle TEXT, $columnDescription TEXT)'
And of course, all requests to the database must be adapted to the new fields so that no errors occur.