我有一个纬度和经度列表,并将它们存储在数据库中。我希望这些纬度和经度可以在带有标记的颤振图中表示出来。
我使用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)
)
]
),
)
);
}
);
}
}
下面是我正在创建dbHelper的数据库类和用于创建表的类说明
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()),);
}
}
现在,我要在主屏幕上写标记
答案 0 :(得分:0)
首先,您应将纬度和经度存储为两个单独的实数值列。这简化了进一步的步骤。
然后,您需要一个标记列表,以后可以作为班级中的字段进行更新:
List<Marker> _markers = [];
要更新标记(例如,从数据库中),请使用以下功能:
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;
});
}
此功能从数据库中获取所有Notes并更新标记。
在FlutterMap小部件中,将标记列表替换为_markers
字段:
MarkerLayerOptions(markers: _markers)
为确保在应用启动后立即加载所有项目,请调用setMarkers()
中的initState()
函数,然后在地图上添加一个可以在您的NoteScreen小部件中创建的新标记。将您的HomeScreen的FloatingActionButton调用替换为
onPressed: () async {
await Navigator.push(
context, MaterialPageRoute(builder: (context) => AddPlantScreen(Plant.empty())));
setMarkers();
},
这会在创建新条目后更新地图。
注意:并非每次都从数据库中清除并完全重新加载数据不是最佳方法,但这取决于您进行优化。
您确实将当前位置分开了:
void getCurrentPosition() async {
Position currentLocation = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
setState(() {
_center = LatLng(currentLocation.latitude, currentLocation.longitude);
});
}
要使其正常工作,您需要做的就是更新Note类以支持double _latitude;
和double _longitude;
而不是String _location;
,因此您需要更新map函数,获取器和构造函数。
此外,您需要调整DatabaseHelper类:
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)'
当然,对数据库的所有请求都必须适应新字段,以免发生错误。