web-dev-qa-db-fra.com

Flutter fenêtre d'informations sur le marqueur Google Map personnalisé

Je travaille sur les marqueurs Google Map à Flutter.

Sur le clic de chaque marqueur, je veux afficher une fenêtre d'informations personnalisées qui peut inclure un bouton, une image, etc. Mais dans Flutter, il y a une propriété TextInfoWindow qui n'accepte que String.

Comment puis-je réaliser l'ajout de boutons et d'images au marqueur de carte InfoWindow.

11
shalini

Ci-dessous, 4 étapes que j'avais mises en place pour InfoWindow personnalisé sur mon projet

Étape 1: créez une pile pour GoogleMap et la fenêtre d'informations personnalisée.

Stack(
    children: <Widget>[
        Positioned.fill(child: GoogleMap(...),),
        Positioned(
            top: {offsetY},
            left: {offsetX},
            child: YourCustomInfoWidget(...),
    ]

Étape 2: Lorsque l'utilisateur clique sur la position de la calculatrice de marqueur du marqueur à l'écran avec func:

screenCoordinate = await _mapController.getScreenCoordinate(currentPosition.target)

Étape 3: Calculatrice offsetY, offsetX et setState.

Problème lié: https://github.com/flutter/flutter/issues/4165

devicePixelRatio = devicePixelRatio = Platform.isAndroid? MediaQuery.of(context).devicePixelRatio: 1.0;

offsetY = screenCoordinate?.y?.toDouble() ?? 0)/devicePixelRatio - infoWidget.size.width
offsetX = (screenCoordinate?.x?.toDouble() ?? 0)/devicePixelRatio - infoWidget.size.height,

Étape 4: Désactivez la caméra de déplacement automatique du marqueur lorsque vous appuyez sur

Marker(
...
consumeTapEvents: true,)
0
dangngocduc

Voici une solution pour créer un marqueur personnalisé qui ne repose pas sur InfoWindow. Bien que cette approche ne vous permette pas d'ajouter un bouton sur un marqueur personnalisé.

Le plugin Flutter google maps nous permet d'utiliser des données/ressources d'image pour créer un marqueur personnalisé. Donc, cette approche utilise le dessin sur Canvas pour créer un marqueur personnalisé et l'utilisation PictureRecorder pour le convertir en image, qui plus tard serait utilisée par le plugin google maps pour le rendu un marqueur personnalisé.

Exemple de code pour dessiner sur Canvas et le convertir en données d'image pouvant être utilisées par le plugin.

void paintTappedImage() async {
    final ui.PictureRecorder recorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(recorder, Rect.fromPoints(const Offset(0.0, 0.0), const Offset(200.0, 200.0)));
    final Paint paint = Paint()
      ..color = Colors.black.withOpacity(1)
      ..style = PaintingStyle.fill;
    canvas.drawRRect(
        RRect.fromRectAndRadius(
            const Rect.fromLTWH(0.0, 0.0, 152.0, 48.0), const Radius.circular(4.0)),
        Paint);
    paintText(canvas);
    paintImage(labelIcon, const Rect.fromLTWH(8, 8, 32.0, 32.0), canvas, Paint,
        BoxFit.contain);
    paintImage(markerImage, const Rect.fromLTWH(24.0, 48.0, 110.0, 110.0), canvas,
        Paint, BoxFit.contain);
    final Picture picture = recorder.endRecording();
    final img = await picture.toImage(200, 200);
    final pngByteData = await img.toByteData(format: ImageByteFormat.png);
    setState(() {
      _customMarkerIcon = BitmapDescriptor.fromBytes(Uint8List.view(pngByteData.buffer));
    });
  }

  void paintText(Canvas canvas) {
    final textStyle = TextStyle(
      color: Colors.white,
      fontSize: 24,
    );
    final textSpan = TextSpan(
      text: '18 mins',
      style: textStyle,
    );
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout(
      minWidth: 0,
      maxWidth: 88,
    );
    final offset = Offset(48, 8);
    textPainter.Paint(canvas, offset);
  }

  void paintImage(
      ui.Image image, Rect outputRect, Canvas canvas, Paint paint, BoxFit fit) {
    final Size imageSize =
        Size(image.width.toDouble(), image.height.toDouble());
    final FittedSizes sizes = applyBoxFit(fit, imageSize, outputRect.size);
    final Rect inputSubrect =
        Alignment.center.inscribe(sizes.source, Offset.zero & imageSize);
    final Rect outputSubrect =
        Alignment.center.inscribe(sizes.destination, outputRect);
    canvas.drawImageRect(image, inputSubrect, outputSubrect, Paint);
  }

une fois que le marqueur est tapé, nous pouvons remplacer l'image tapée par la nouvelle image générée à partir de Canvas. Exemple de code pour le même extrait de l'application d'exemple de plugin google maps.

void _onMarkerTapped(MarkerId markerId) async {
  final Marker tappedMarker = markers[markerId];
  if (tappedMarker != null) {
    if (markers.containsKey(selectedMarker)) {
      final Marker resetOld =
      markers[selectedMarker].copyWith(iconParam: _markerIconUntapped);
      setState(() {
        markers[selectedMarker] = resetOld;
      });
    }
    Marker newMarker;
    selectedMarker = markerId;
    newMarker = tappedMarker.copyWith(iconParam: _customMarkerIcon);
    setState(() {
      markers[markerId] = newMarker;
    });
    tappedCount++;
  }
}

Référence:

Comment convertir une toile flottante en Image .

exemple d'application du plugin Flutter.

Google maps flutter plugin custom marker in action.

0
Ashildr