Местоположение маркировки Flutter (широта, долгота) на карте Flutter из базы данных Sqflite

У меня есть список широты и долготы, которые я храню в базе данных. Я хочу, чтобы эти широта и долгота были представлены на карте флаттера с маркерами.

Мой код для сохранения широты и долготы с помощью 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()),);
                }
}

Теперь, используя это, я хочу написать маркер на главном экране.

Пробовали ли вы следовать этому курсу: codelabs.developers.google.com/codelabs/google-maps-in-flutt‌​er? В нем объясняется, как использовать Google Maps с Flutter и как устанавливать маркеры на карте. Виджет GoogleMap содержит свойство markers, где вы можете передать набор маркеров, которые вы читаете из своей базы данных SQLite, для отображения.

Martin Niederl 28.05.2019 11:21

Да, я прошел через это, но в моем случае я получаю местоположение в реальном времени и сохраняю его вместе с некоторыми другими данными, из этих данных я хочу получить маркеры местоположения. Я обновил свой код выше, пожалуйста, просмотрите его. @MartinNiederl

Mahant 28.05.2019 12:11

и я не использую карту Google, вместо этого я использую пакет флаттер карта

Mahant 28.05.2019 12:25

В чем проблема с кодом или что вы хотите, чтобы мы для вас исправили? Пожалуйста, объясните, в чем именно проблема, потому что код в основном выглядит так, как будто вы знаете, что делаете.

Martin Niederl 28.05.2019 14:32

Я хочу использовать данные о местоположении, которые я сохраняю в базе данных, и я хочу передать список данных о местоположении маркерам и показать маркеры на главном экране карты. Не могли бы вы помочь мне в этом?

Mahant 28.05.2019 14:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
12 410
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прежде всего, вы должны хранить широту и долготу как два отдельных столбца реальных значений. Это упрощает дальнейшие действия.

Затем вам нужен список маркеров, который можно обновить позже как поле в классе:

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)

Чтобы убедиться, что все элементы загружаются вскоре после запуска приложения, вызовите функцию setMarkers() в initState() и добавьте новый маркер, который можно создать в вашем виджете NoteScreen, на карту замените вызов из FloatingActionButton HomeScreen на

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);
    });
  }

Что вам нужно сделать, чтобы это заработало, так это обновить класс Note, чтобы он поддерживал double _latitude; и double _longitude; вместо String _location;. Поэтому вам нужно обновить функции карты, геттеры и конструктор.

Кроме того, вам необходимо настроить класс 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)'

И конечно, все запросы к БД должны быть адаптированы к новым полям, чтобы не возникало ошибок.

Ответ выглядит чистым, и я попытался сохранить широту и язык как отдельные, но я не могу сохранить широту и долготу как отдельные значения, поскольку я получаю оба значения как одно значение, вызывая текущее местоположение, не могли бы вы предложить мне, как сохранить широту и язык как отдельные значения в базе данных. Это было бы большим подспорьем.

Mahant 29.05.2019 07:31

Если у вас остались вопросы, свяжитесь со мной по официальному адресу fluttercommunity.slack.com в прямом сообщении и проголосуйте/примите ответ, если он вам помог.

Martin Niederl 29.05.2019 10:50

У меня нет 50 репутаций, чтобы проголосовать, однако я проголосовал за ваш ответ, но здесь он не отразится. Как я могу присоединиться к fluttercommunity.slack.com. Можешь прислать мне ссылку-приглашение

Mahant 29.05.2019 11:07

Другие вопросы по теме