Skip to content

Conversation

@pamtbaau
Copy link
Contributor

As discussed, I've created this PR to discuss the possible implementation of Annotations to Markers.

Summary:

  • In widget-layer.dart:
    • Added class Annotation
      Annotation can have any widget as child, including Gestures.
    • Added List<Annotation> annotations to class Marker
    • Extended build() to create and position Annotations relative to Marker
  • In example widget_layer_interactive_page.dart:
    • Extended Markers with list of Annotations.
    • Set Offset of Annotation to finetune its position relative to Marker
    • Added function Size _calculateTextSize(Text textWidget) to calculate width and height of Text widget needed to horizontally/vertically align with centers of Marker.

Issue:

  • Vertical alignment of Text does not work perfectly for centerLeft and centerRight.

Any feedback/suggestion is welcome.

@codecov
Copy link

codecov bot commented Mar 21, 2025

Codecov Report

Attention: Patch coverage is 51.85185% with 26 lines in your changes missing coverage. Please review.

Project coverage is 61.98%. Comparing base (1df507b) to head (6727a3c).
Report is 8 commits behind head on main.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@josxha
Copy link
Owner

josxha commented Apr 9, 2025

Sorry for your long wait for a response @pamtbaau. I finally had time to look at your pull requests in detail. I still think that adding marker annotation is a great idea - so let's try solving the alignment issues.

I recommend to enable the "Show Guidelines" option in the flutter dev tools while working with Markers to see the outlines.
Here I created a simple Marker where the content fits the Marker.size:

Marker(
  point: Position(0, 0),
  size: const Size.square(150),
  child: Container(color: Colors.red, width: 150, height: 150),
),

When we change Marker.child to a Text widget, the text shows up in the top left corner. The light blue line indicates the boundaries of the Positioned widget used by the Marker.

We are now able to align the text for example to the center right side using a Align widget.

Marker(
  point: Position(0, 0),
  size: const Size.square(150),
  child: const Align(
    alignment: Alignment.centerRight,
    child: Text(
      'Marker',
      style: TextStyle(color: Colors.red, fontSize: 20),
    ),
  ),
),

We could use the same for annotations where the Annotation defines the maximum area the child widget has to display its content. However for this to work, we need to define the height and width properties of the used Positioned widget.
Currently, the annotation widgets expands towards one side, even when a centered alignment is selected. The Text widgets where a bit hard to see for me, so I replaced them with colored boxes.


Complete code sample of the screenshot (click to expand)

Alignment.center and Alignment.bottomCenter somehow had some problems when I tried to use them.

import 'package:flutter/material.dart';
import 'package:maplibre/maplibre.dart';

@immutable
class WidgetLayerPage extends StatefulWidget {
  const WidgetLayerPage({super.key});

  static const location = '/widget-layer';

  @override
  State<WidgetLayerPage> createState() => _WidgetLayerPageState();
}

class _WidgetLayerPageState extends State<WidgetLayerPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Widget Layer')),
      body: MapLibreMap(
        options: MapOptions(initZoom: 3, initCenter: Position(0, 0)),
        children: [
          WidgetLayer(
            markers: [
              Marker(
                point: Position(0, 0),
                size: const Size.square(150),
                child: const _Marker(),
                annotations: const [
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.topLeft,
                  ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.topCenter,
                  ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.topRight,
                  ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.centerLeft,
                  ),
                  Annotation(
                    child: Text(
                      'centerLeft',
                      style: TextStyle(
                        color: Colors.purpleAccent,
                        fontSize: 30,
                      ),
                    ),
                    alignment: Alignment.centerLeft,
                  ),
                  // Annotation(
                  //   child: _Annotation(),
                  //   alignment: Alignment.center,
                  // ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.centerRight,
                  ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.bottomLeft,
                  ),
                  // Annotation(
                  //   child: _Annotation(),
                  //   alignment: Alignment.bottomCenter,
                  // ),
                  Annotation(
                    child: _Annotation(),
                    alignment: Alignment.bottomRight,
                  ),
                ],
              ),
            ],
          ),
          // display the UI widgets above the widget markers.
          const SourceAttribution(),
        ],
      ),
    );
  }
}

class _Annotation extends StatelessWidget {
  const _Annotation();

  @override
  Widget build(BuildContext context) {
    return Container(color: Colors.purple, width: 20, height: 20);
  }
}

class _Marker extends StatelessWidget {
  const _Marker();

  @override
  Widget build(BuildContext context) {
    return Container(color: Colors.red, width: 150, height: 150);
  }
}

To sum it all up, I'd do the following changes

  • use the width and height parameters of the Positioned widget
  • calculate the Positioned left / top / bottom / right parameter based on Annotation.alignment and the (maximum) width / height of the Annotation.
  • If the user needs to align the widget to the center or something else, he can wrap his content inside a Align widget.

Calculating the used height of the font is a nice idea, but I'm not sure if it would cause some problems, for example if the user increased the size of all texts on the device.

@josxha josxha marked this pull request as draft April 9, 2025 21:57
@pamtbaau
Copy link
Contributor Author

pamtbaau commented May 4, 2025

@josxha, just to let you know, my attention has shifted away from flutter_maplibre and back to mapsforge_flutter. I needed areal images and was under the impression that mapsforge_flutter was only about offline openstreetmaps maps. I was wrong...

@pamtbaau pamtbaau closed this May 4, 2025
@github-project-automation github-project-automation bot moved this from Backlog to Done in maplibre dev May 4, 2025
@josxha
Copy link
Owner

josxha commented May 6, 2025

@pamtbaau Thanks for the update, no worries.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants