Введение
Понадобилась мне как-то карта во флаттер-приложении. Гугл и яндекс карты использовать не хотелось и оставалось только воспользоваться OSM. Ну и понадобилось добавить всплывающее окно при нажатии на маркер положения на карте, нашел как это делать для гугла и яндекса, а для flutter_mup не сразу нашел. Но оказалось есть плагин flutter_map_marker_popup.
Смотрим плагин
Зависимости укажем такие:
dependencies:
flutter:
sdk: flutter
flutter_map: any
latlong2: any
flutter_map_marker_popup: any
Для начала нам потребуется карта Flutter_map, на которой уже будем располагать наши маркеры. Добавим ее
class MapPage extends StatefulWidget {
MapPage({super.key, required this.center, double? zoom}){
this.zoom = zoom ?? 9.0;
}
final LatLng center;
late final double zoom;
@override
State<MapPage> createState() => _MapPageState();
}
class _MapPageState extends State<MapPage> {
final urlTemplate = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Map page"),
),
body: FlutterMap(
mapController: MapController(),
options: MapOptions(
center: widget.center,
zoom: widget.zoom,
),
children: [
TileLayer(
urlTemplate: urlTemplate,
),
],
),
);
}
}
Дальше давайте как-то добавлять маркеры на карту и отобразим их стандартным образом. Добавим лист маркеров, и функцию добавить маркер. В MapOptions добавим onLongPress: addMarker.
final List<Marker> _markers = [];
addMarker(tapPosition, point){
_markers.add(Marker(
point: point,
builder: (c) => const Icon(Icons.location_on, size: 40),
width: 40,
height: 40,));
}
Теперь эти маркеры можно стандартно отобразить с помощью слоя MarkerLayer(markers: _markers,)
, но тогда не получится отслеживать нажатие по ним и отображать что-либо. Для этих задач в плагине flutter_map_marker_popup есть PopupMarkerLayerWidget
. Добавляем этот слой
PopupMarkerLayerWidget(
options: PopupMarkerLayerOptions(
popupController: _popupLayerController,
markers: _markers,
markerRotateAlignment:
PopupMarkerLayerOptions.rotationAlignmentFor(AnchorAlign.top),
popupBuilder: (BuildContext context, Marker marker) =>
ExamplePopup(marker),
),
),
Ага, мы передаем туда все маркеры и что-то с ними делаем. Что такое ExamplePopup
? Собственно в нем будут правила отображения всплывающего окна. Смотрим:
class ExamplePopup extends StatefulWidget {
final Marker marker;
const ExamplePopup(this.marker, {Key? key}) : super(key: key);
@override
State<StatefulWidget> createState() => _ExamplePopupState();
}
class _ExamplePopupState extends State<ExamplePopup> {
int _currentIcon = 0;
@override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: () => setState(() {
_currentIcon = (_currentIcon + 1) % 4;
}),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(left: 20, right: 10),
child: Image.asset('assets/${_currentIcon+1}.png', width: 40, height: 40,),
),
_cardDescription(context),
],
),
),
);
}
Widget _cardDescription(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(10),
child: Container(
constraints: const BoxConstraints(minWidth: 100, maxWidth: 200),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text(
'Popup for a marker!',
overflow: TextOverflow.fade,
softWrap: false,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 14.0,
),
),
const Padding(padding: EdgeInsets.symmetric(vertical: 4.0)),
Text(
'Position: ${widget.marker.point.latitude}, ${widget.marker.point.longitude}',
style: const TextStyle(fontSize: 12.0),
),
Text(
'Marker size: ${widget.marker.width}, ${widget.marker.height}',
style: const TextStyle(fontSize: 12.0),
),
],
),
),
);
}
}
Примечание, для получения картинок из папки assets надо в pubspec.yml добавить настройку:
flutter:
assets:
- assets/
И вот раз, и у нас по нажатию на маркер всплывает окно с котиками.
Всем спасибо! Если интересно, есть телеграмм, заходите присаживайтесь).
Top comments (0)