Sqflite 数据库的 Flutter 地图上的 Flutter 标记位置(纬度,经度)

Flutter Marking locations (Latitude, Longitude) on Flutter Map from Sqflite Database

我有纬度和经度列表,我将它们存储在 database.I 希望这些纬度和经度在带有标记的颤动地图中表示。

我使用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)
                    )
                  ]
              ),
            )
          );
      }
    );
  }
}

下面是我的数据库 classes,我正在其中创建 dbHelper 和 class 创建 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()),);
                }
}

现在使用这个我想在我的主屏幕上写标记

首先,您应该将纬度和经度存储为两个单独的实数值列。这简化了进一步的步骤。

然后您需要一个标记列表,稍后可以将其更新为 class:

中的字段
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;
  });
}

此函数从数据库中获取所有注释并更新标记。

在 FlutterMap 小部件中,将标记列表替换为 _markers 字段:

MarkerLayerOptions(markers: _markers)

为确保在应用程序启动后不久加载所有项目,请调用 initState() 中的 setMarkers() 函数并添加一个新的标记(可以在您的 NoteScreen 小部件中创建)以地图将主屏幕的 FloatingActionButton 的调用替换为

onPressed: () async {
  await Navigator.push(
      context, MaterialPageRoute(builder: (context) => AddPlantScreen(Plant.empty())));
  setMarkers();
},

这会在创建新条目后更新地图。

注意:每次从数据库中清除并完全重新加载数据并不是最好的方法,但这取决于您的优化。

编辑#1:

你确实得到了当前位置的分隔:

  void getCurrentPosition() async {
    Position currentLocation = await Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high);

    setState(() {
      _center = LatLng(currentLocation.latitude, currentLocation.longitude);
    });
  }

你需要做的是更新你的笔记 class 以支持 double _latitude;double _longitude; 而不是 String _location; 所以你需要更新地图函数、getter 和构造函数。

此外,您需要调整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)'

当然,所有对数据库的请求都必须适应新字段,以免发生错误。