DEV Community

Cover image for Попап на флаттер карте или flutter_map_marker_popup
AVTarasov210
AVTarasov210

Posted on

2 1

Попап на флаттер карте или flutter_map_marker_popup

Введение

Понадобилась мне как-то карта во флаттер-приложении. Гугл и яндекс карты использовать не хотелось и оставалось только воспользоваться OSM. Ну и понадобилось добавить всплывающее окно при нажатии на маркер положения на карте, нашел как это делать для гугла и яндекса, а для flutter_mup не сразу нашел. Но оказалось есть плагин flutter_map_marker_popup.

Смотрим плагин

Зависимости укажем такие:

dependencies:
  flutter:
    sdk: flutter
  flutter_map: any
  latlong2: any
  flutter_map_marker_popup: any
Enter fullscreen mode Exit fullscreen mode

Для начала нам потребуется карта 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,
          ),
        ],
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Дальше давайте как-то добавлять маркеры на карту и отобразим их стандартным образом. Добавим лист маркеров, и функцию добавить маркер. В 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,));
  }
Enter fullscreen mode Exit fullscreen mode

Теперь эти маркеры можно стандартно отобразить с помощью слоя 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),
            ),
          ),
Enter fullscreen mode Exit fullscreen mode

Ага, мы передаем туда все маркеры и что-то с ними делаем. Что такое 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),
            ),
          ],
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Примечание, для получения картинок из папки assets надо в pubspec.yml добавить настройку:

flutter:
  assets:
    - assets/
Enter fullscreen mode Exit fullscreen mode

И вот раз, и у нас по нажатию на маркер всплывает окно с котиками.

Всем спасибо! Если интересно, есть телеграмм, заходите присаживайтесь).

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay