Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MapLibre Android: Using textField on SymbolLayer/SymbolOptions makes the symbol invisible. #60

Open
EllisGlaeser opened this issue May 31, 2024 · 16 comments
Labels
bug Something isn't working needs-more-info Further information is requested

Comments

@EllisGlaeser
Copy link

EllisGlaeser commented May 31, 2024

Using the SymbolManager or SymbolLayer to display symbols is working fine, but as soon as I add the textField property, it breaks the symbol and it no longer appears.

I have read several past issues similar to this where people have said it's related to the font, but I just want to use the default font and can't even figure out a way to change where the font is coming from, just the textFont property that wants the font name.

I am using the default Style Builder:

mapboxMap.setStyle(Style.Builder())

This is how I'm adding the source & layer (from a custom waypoint class):

val identifier = waypoint.icon().id()
val feature = Feature.fromGeometry(Point.fromLngLat(waypoint.backing.longitude, waypoint.backing.latitude))
val point = FeatureCollection.fromFeature(feature)
val source = GeoJsonSource(identifier, point)
val symbolLayer = SymbolLayer(GPMapLayers.WAYPOINTS.layerID + waypoint.uuid, identifier).withProperties(
      PropertyFactory.iconImage(identifier),
      PropertyFactory.textField(waypoint.title()),
      PropertyFactory.textSize(12f),
      PropertyFactory.textColor("#000000")
)

style.addSource(source)
style.addLayer(symbolLayer)

I have also tried passing "sans-serif" (the default Android font as well as the default font for MapLibre Android), as well as Open Sans Regular & Arial Unicode MS Regular, the defaults for MapBox.

I was using an older version of MapLibre Android, but updated to Version 11 to try and fix the problem. With the older version, I was using a SymbolManager to add the symbols to the map, but it appears MapLibre 11 doesn't support the Annotation Plugin. Is this the case, or am I missing something?

@EllisGlaeser EllisGlaeser added the bug Something isn't working label May 31, 2024
@louwers
Copy link
Collaborator

louwers commented May 31, 2024

Could you share the snippet that doesn't work?

We released a new version of the Annotation plugin that is compatible with MapLibre Native Android 11.0.0.

@EllisGlaeser
Copy link
Author

Where I used to be using the Symbol Manager, it won't let me, saying the SymbolManager needs a MapboxMap as a param instead of MapLibreMap.

val symbolManager = SymbolManager(mapView, mapLibreMap, style)
symbolManager.iconAllowOverlap = true
symbolManager.textAllowOverlap = true
symbolManager.iconIgnorePlacement = true
symbolManager.addDragListener(this)
this.symbolManager = symbolManager

What's the new version of the plugin?
I see this, but that doesn't get me the SymbolManager. Is this something different?:
implementation 'com.maplibre.maplibresdk:maplibre-android-plugin-annotation-v9:0.9.0' from https://github.com/maplibre/maplibre-plugins-android/tree/main/plugin-annotation

This is what I have currently:
implementation 'org.maplibre.gl:android-plugin-annotation-v9:1.0.0'

The code for the symbol layer works just fine if I take out the textField, but as soon as I add that the symbol disappears completely.

@louwers
Copy link
Collaborator

louwers commented Jun 1, 2024

Try using the latest version from Maven Central (3.0.0) https://central.sonatype.com/artifact/org.maplibre.gl/android-plugin-annotation-v9

@EllisGlaeser
Copy link
Author

Okay, I updated to that version and I get the SymbolManager again, but adding the textField still prevents the symbol from appearing on the map.

This is the simplest way I've tried it:

var symbol = SymbolOptions()
          withLatLng(waypoint.latLng())
          .withIconImage(identifier)
          .withIconSize(scale)
          .withTextField(waypoint.title())
symbolMgr.create(symbol)

@EllisGlaeser
Copy link
Author

Do you have any other ideas? Is this just a bug in the code, or is there anything else I can do to make it work?

@alminav
Copy link

alminav commented Jun 14, 2024

Have the same problem with org.maplibre.gl:android-sdk:11.0.0

@louwers louwers transferred this issue from maplibre/maplibre-native Jun 15, 2024
@louwers
Copy link
Collaborator

louwers commented Jun 15, 2024

I am unable to reproduce this. When I edit BulkSymbolActivity.java and use withTextField

            options.add(new SymbolOptions()
                .withGeometry((Point) feature.geometry())
                .withIconImage(IMAGE_ID_FIRE_HYDRANT)
                .withTextField("Test")

The text label shows up as expected.

Could you try to reproduce this problem using the demo app in this repo?

image

@louwers louwers added the needs-more-info Further information is requested label Jun 15, 2024
@EllisGlaeser
Copy link
Author

EllisGlaeser commented Jun 18, 2024

Yes, the sample app works. My implementation uses Kotlin + Jetpack Compose and hosts the MapView in an AndroidView. Is that the difference?
I tried to create a sample version of what I'm doing but I'm having trouble getting a map style to load like how the sample app does.

@EllisGlaeser
Copy link
Author

EllisGlaeser commented Jul 2, 2024

It seems like this is related to how I am loading the map. We have a selection of maps that we load by adding a custom Source class via a RasterLayer like this:

val mbSource = this.activeMBSource
if (mbSource != null) {
     val s = mbSource.maplibreSource
     val activeMapSource = style.getSource(s.id)

 // If mbSource contains raster tiles
     val rasterLayer = RasterLayer("basemap_layer_id", mbSource.sourceId)
      rasterLayer.maxZoom = mbSource.mapSource.maxZoomLevel.toFloat()
       style.addLayer(rasterLayer)

   // If mbSource contains vector tiles
       val vectorLayer = LineLayer("vector_layer_id", mbSource.sourceId)
       style.addLayer(vectorLayer)
}

As soon as I switched to a MapTiler map like this, the waypoint title worked just fine:

val mapId = "streets-v2"
val styleUrl = "https://api.maptiler.com/maps/$mapId/style.json?key=$key"

@EllisGlaeser
Copy link
Author

EllisGlaeser commented Jul 2, 2024

Does the textField only work when you're using vector maps? Here's a simple example you can try out to replicate it. In this case, the symbol doesn't appear even when the textField isn't there, which isn't the problem I'm having in my actual project, but I'm assuming they are related. Without the map source, the marker appears on the black screen, but once you add the raster source it doesn't show.

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        MapLibre.getInstance(this)

        mapView = MapView(this)

        setContent {
            loadMap(mapView)
            MapLibreSymbolsExampleTheme {
                AndroidView(
                    {
                        mapView
                    }
                )
            }
        }
    }

    private fun loadMap(mapView: MapView) {
        mapView.getMapAsync { map ->
            map.setStyle(Style.Builder()) { style ->
                val sourceURL = "https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}"
                val source = RasterSource("usNat", TileSet("3.0.0", sourceURL))
                val sourceID = "usNat"

                val coordinate = LatLng(48.11166, 121.11486)

                val symbolManager = SymbolManager(mapView, map, style)
                val imgName = "Point"
                val bmp = BitmapFactory.decodeResource(this@MainActivity.resources, R.drawable.markerbrown)

                // Once you add the source, you can't see the image.
//                style.addSource(source)
                style.addLayer(RasterLayer("map-layer", sourceID))
                style.addImage(imgName, bmp)

                symbolManager.create(
                    SymbolOptions()
                        .withLatLng(coordinate)
                        .withIconImage(imgName)
                        .withIconSize(1f)
                        .withSymbolSortKey(1f)
                        // If you take out the text field, the marker appears.
//                        .withTextField(imgName)
                )

                map.cameraPosition = CameraPosition.Builder().target(coordinate).zoom(10.0).build()
            }
        }
    }
    implementation ("org.maplibre.gl:android-sdk:11.0.0")
    implementation("org.maplibre.gl:android-plugin-annotation-v9:3.0.0")

Here is the image I'm using:

markerbrown

@alminav
Copy link

alminav commented Jul 4, 2024 via email

@EllisGlaeser
Copy link
Author

Update: I was able to fix this issue by using a style json instead of the default Style.Builder, and providing

styleJson.put("glyphs", "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf")

@pstanoev
Copy link

pstanoev commented Sep 23, 2024

I have the same issue, text works with style from MapTiler, but not with custom style and custom tile server.
It works if the glyphs part of the style JSON is replaced with:
"glyphs": "https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf",
or:
"glyphs": "https://api.maptiler.com/fonts/{fontstack}/{range}.pbf?key=<mykey>",

I guess it is something font related?
Adding textField breaks the annotation , not even the icon is shown.

Update:
it is connected with the default font in MapLibre "Open Sans Regular,Arial Unicode MS Regular".
maplibre/maplibre-style-spec#311

This font is missing on our server.

Can be avoided by specifying the font explicitly:

textFont(arrayOf("Metropolis Regular", "Noto Sans Regular")),
textField(literal("the text"))

@ravenfeld
Copy link
Contributor

Is it the same problem? I've noticed that even without text, if I make an orientation, certain symbols disappear.

This was done on the example application just now.

Screen_recording_20241018_204523.mp4

@EllisGlaeser
Copy link
Author

Is it the same problem? I've noticed that even without text, if I make an orientation, certain symbols disappear.

This was done on the example application just now.

Screen_recording_20241018_204523.mp4

If you set iconAllowOverlap to true and set iconOptional to false in your SymbolManager it should help. I still have occasional times where symbols will disappear for certain zoom levels and I haven't been able to figure out why, but setting these params takes care of most cases.

@ravenfeld
Copy link
Contributor

Yes, that's it. So now I understand the problem with fixing it. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working needs-more-info Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants