如何在android中使用mapbox添加动态符号图层

问题描述 投票:0回答:2

我正在使用地图盒 Android SDK 来使用地图。

我正在使用符号图层在地图中添加动态符号。

我的代码:

for (Feature feature : featureCollection.features()) {
String report_id = feature.getStringProperty("report_id");
switch (report_id) {
                        case "1": {
                            Bitmap bitmap = null;
                            Drawable drawable = ContextCompat.getDrawable(activity, R.mipmap.ic_location_black);
                            if (drawable instanceof BitmapDrawable) {
                                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                                if (bitmapDrawable.getBitmap() != null) {
                                    bitmap = bitmapDrawable.getBitmap();
                                }
                            } else {
                                if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
                                    bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
                                } else {
                                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                                }

                                Canvas canvas = new Canvas(bitmap);
                                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                                drawable.draw(canvas);
                            }

                            if (bitmap != null) {
                                mapboxMap.getStyle().addImage(MARKER_IMAGE_ID + report_id, bitmap);
                            }
                            mapboxMap.getStyle().addLayer(new SymbolLayer(MARKER_IMAGE_ID + report_id, GEOJSON_SOURCE_ID)
                                    .withProperties(
                                            iconImage(MARKER_IMAGE_ID + report_id),
                                            iconAllowOverlap(true),
                                            iconSize(0.7f)
                                    ));
                            break;
                        }
                        case "2": {
                            Bitmap bitmap = null;
                            Drawable drawable = ContextCompat.getDrawable(activity, R.mipmap.ic_current_pin);
                            if (drawable instanceof BitmapDrawable) {
                                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                                if (bitmapDrawable.getBitmap() != null) {
                                    bitmap = bitmapDrawable.getBitmap();
                                }
                            } else {
                                if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
                                    bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
                                } else {
                                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                                }

                                Canvas canvas = new Canvas(bitmap);
                                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                                drawable.draw(canvas);
                            }

                            if (bitmap != null) {
                                mapboxMap.getStyle().addImage(MARKER_IMAGE_ID + report_id, bitmap);
                            }
                            mapboxMap.getStyle().addLayer(new SymbolLayer(MARKER_IMAGE_ID + report_id, GEOJSON_SOURCE_ID)
                                    .withProperties(
                                            iconImage(MARKER_IMAGE_ID + report_id),
                                            iconAllowOverlap(true),
                                            iconSize(0.7f)
                                    ));
                            break;
                        }
                        case "3": {
                            Bitmap bitmap = null;
                            Drawable drawable = ContextCompat.getDrawable(activity, R.mipmap.ic_current_location);
                            if (drawable instanceof BitmapDrawable) {
                                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                                if (bitmapDrawable.getBitmap() != null) {
                                    bitmap = bitmapDrawable.getBitmap();
                                }
                            } else {
                                if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
                                    bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
                                } else {
                                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                                }

                                Canvas canvas = new Canvas(bitmap);
                                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                                drawable.draw(canvas);
                            }

                            if (bitmap != null) {
                                mapboxMap.getStyle().addImage(MARKER_IMAGE_ID + report_id, bitmap);
                            }
                            mapboxMap.getStyle().addLayer(new SymbolLayer(MARKER_IMAGE_ID + report_id, GEOJSON_SOURCE_ID)
                                    .withProperties(
                                            iconImage(MARKER_IMAGE_ID + report_id),
                                            iconAllowOverlap(true),
                                            iconSize(0.7f)
                                    ));
                            break;
                        }
                        default: {
                            Bitmap bitmap = null;
                            Drawable drawable = ContextCompat.getDrawable(activity, R.mipmap.ic_location_transparent);
                            if (drawable instanceof BitmapDrawable) {
                                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                                if (bitmapDrawable.getBitmap() != null) {
                                    bitmap = bitmapDrawable.getBitmap();
                                }
                            } else {
                                if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) {
                                    bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); // Single color bitmap will be created of 1x1 pixel
                                } else {
                                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
                                }

                                Canvas canvas = new Canvas(bitmap);
                                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                                drawable.draw(canvas);
                            }

                            if (bitmap != null) {
                                mapboxMap.getStyle().addImage(MARKER_IMAGE_ID + report_id, bitmap);
                            }
                            mapboxMap.getStyle().addLayer(new SymbolLayer(MARKER_IMAGE_ID + report_id, GEOJSON_SOURCE_ID)
                                    .withProperties(
                                            iconImage(MARKER_IMAGE_ID + report_id),
                                            iconAllowOverlap(true),
                                            iconSize(0.7f)
                                    ));
                            break;
                        }
                    }
}

但是我得到的是所有符号中的所有图像,而不是像这样的特定单个符号中的单个图像

https://www.screencast.com/t/hcoetxj0G

我想为单个符号层生成单个图像。

请知道答案的人帮帮我。

android mapbox mapbox-android
2个回答
0
投票

我使用了https://www.diffchecker.com/,看起来 switch/case 部分的各个部分之间的唯一区别是您正在使用的 mipmap 图像。如果是这样,我会考虑使用 Maps SDK 的匹配表达式来设置图标。请参阅https://docs.mapbox.com/android/maps/examples/marker-symbol-layer/。我已经采取了 https://docs.mapbox.com/android/maps/examples/marker-symbol-layer/ 并进行了调整以匹配您所拥有的

import android.graphics.BitmapFactory;
import android.os.Bundle;

import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Point;
import com.mapbox.mapboxandroiddemo.R;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.Style;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;

import java.util.ArrayList;
import java.util.List;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconIgnorePlacement;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;

/**
 * Display {@link SymbolLayer} icons on the map.
 */
public class BasicSymbolLayerActivity extends AppCompatActivity implements
  OnMapReadyCallback {

  private static final String SOURCE_ID = "SOURCE_ID";
  private static final String ICON_ID = "ICON_ID";
  private static final String LAYER_ID = "LAYER_ID";
  private MapView mapView;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Mapbox access token is configured here. This needs to be called either in your application
    // object or in the same activity which contains the mapview.
    Mapbox.getInstance(this, getString(R.string.access_token));

    // This contains the MapView in XML and needs to be called after the access token is configured.
    setContentView(R.layout.activity_style_basic_symbol_layer);

    mapView = findViewById(R.id.mapView);
    mapView.onCreate(savedInstanceState);
    mapView.getMapAsync(this);
  }

  @Override
  public void onMapReady(@NonNull final MapboxMap mapboxMap) {

    List<Feature> symbolLayerIconFeatureList = new ArrayList<>();
    symbolLayerIconFeatureList.add(Feature.fromGeometry(
      Point.fromLngLat(-57.225365, -33.213144)));
    symbolLayerIconFeatureList.add(Feature.fromGeometry(
      Point.fromLngLat(-54.14164, -33.981818)));
    symbolLayerIconFeatureList.add(Feature.fromGeometry(
      Point.fromLngLat(-56.990533, -30.583266)));

    mapboxMap.setStyle(new Style.Builder().fromUri("mapbox://styles/mapbox/cjf4m44iw0uza2spb3q0a7s41")

        // Add the SymbolLayer icon image to the map style
        .withImage("black_location_icon_id", BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_location_black))
        .withImage("current_pin_icon_id", BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_current_pin))
        .withImage("current_location_icon_id", BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_current_location))
        .withImage("location_transparent_icon_id", BitmapFactory.decodeResource(activity.getResources(), R.drawable.ic_location_transparent))


        // Adding a GeoJson source for the SymbolLayer icons.
        .withSource(new GeoJsonSource(SOURCE_ID,
            FeatureCollection.fromFeatures(symbolLayerIconFeatureList)))

        // Adding the actual SymbolLayer to the map style. An offset is added that the bottom of the red
        // marker icon gets fixed to the coordinate, rather than the middle of the icon being fixed to
        // the coordinate point. This is offset is not always needed and is dependent on the image
        // that you use for the SymbolLayer icon.
        .withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
            .withProperties(
                iconImage(match(get("report_id"), literal("location_transparent_icon_id"),
                    stop(literal("1"), "black_location_icon_id"),
                    stop(literal("2"), "current_pin_icon_id"),
                    stop(literal("3"), "current_location_icon_id"))),
                iconAllowOverlap(true),
                iconIgnorePlacement(true),
                iconAllowOverlap(true),
                iconSize(0.7f)
            )
        ), new Style.OnStyleLoaded() {
      @Override
      public void onStyleLoaded(@NonNull Style style) {

        // Map is set up and the style has loaded. Now you can add additional data or make other map adjustments.


      }
    });
  }

  @Override
  public void onResume() {
    super.onResume();
    mapView.onResume();
  }

  @Override
  protected void onStart() {
    super.onStart();
    mapView.onStart();
  }

  @Override
  protected void onStop() {
    super.onStop();
    mapView.onStop();
  }

  @Override
  public void onPause() {
    super.onPause();
    mapView.onPause();
  }

  @Override
  public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
  }

  @Override
  protected void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
  }

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
  }
}

地图 SDK 还具有

addOnStyleImageMissingListener
https://docs.mapbox.com/android/maps/examples/missing-icon/

另外,我会使用以下内容代替

mapboxMap.getStyle()
mapboxMap.getStyle()
有机会回归
null

mapboxMap.getStyle(new Style.OnStyleLoaded() {
              @Override
              public void onStyleLoaded(@NonNull Style style) {

              }
            });

0
投票

MapBox 版本 10

自定义符号层

在地图上显示不同类型的兴趣点,例如卫生间、步道起点和野餐区。为此,我们将为每个 POI 类别定义自定义符号并将其覆盖在地图上。

mapView.getMapboxMap().loadStyle(
    styleExtension = style(Style.TRAFFIC_NIGHT) {

        // Define custom images for symbols
        +image(RESTROOMS) {
            bitmap(drawableIdToBitmap(requireContext(), R.drawable.ic_rest_rooms))
        }
        +image(TRAIL_HEAD) {
            bitmap(drawableIdToBitmap(requireContext(), R.drawable.ic_trail_head))
        }
        +image(PICNIC_AREA) {
            bitmap(drawableIdToBitmap(requireContext(), R.drawable.ic_panic_area))
        }

        +symbolLayer(LAYER_ID, SOURCE_ID) {
            sourceLayer(CIRLCE_LAYER_ID)

            // Assign the appropriate icon image based on the POI type
            iconImage(
                switchCase {
                    eq {
                        get {
                            literal(ICON_KEY)
                        }
                        literal(KEY_PICNIC_AREA)
                    }
                    literal(PICNIC_AREA)
                    eq {
                        get {
                            literal(ICON_KEY)
                        }
                        literal(KEY_RESTROOMS)
                    }
                    literal(RESTROOMS)
                    eq {
                        get {
                            literal(ICON_KEY)
                        }
                        literal(KEY_TRAIL_HEAD)
                    }
                    literal(TRAIL_HEAD)
                    // Default case is to return an empty string so no icon will be loaded
                    literal("")
                }
            )
            iconAllowOverlap(true)
            iconAnchor(IconAnchor.BOTTOM)

            // Display text for each POI
            textField(
                Expression.get(TEXT_KEY)
            )
            textColor("#FFFFFF")
        }
    }
)

在上面的代码中,我们为卫生间、步道起点和野餐区符号定义了自定义图像。

symbolLayer
用于指定这些符号在地图上的显示方式。
iconImage
属性根据 POI 类型动态选择适当的图标,并且我们还为每个 POI 显示文本。

数据来源

要使用数据填充我们的自定义符号图层,我们需要一个数据源。在此示例中,我们将使用包含示例数据的 GeoJSON 源。

private val samplejson = """{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-122.4167, 37.7833]
      },
      "properties": {
        "name": "Golden Gate Bridge",
        "POITYPE": "Restroom",
        "TEXT_KEY": "Rest Room"
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "Point",
        "coordinates": [-122.4084, 37.7833]
      },
      "properties": {
        "name": "Golden Gate Park",
        "POITYPE": "Trailhead",
        "TEXT_KEY": "Trail heading"
      }
    }
  ]
}"""

此 GeoJSON 源包含两个表示兴趣点的要素,每个要素都有一个位置、名称、POI 类型以及要在地图上显示的文本。

### Adding the Data to the Map

最后,我们将 GeoJSON 数据添加到地图中,并将其与我们之前定义的符号图层关联起来。

val geoJsonSource = GeoJsonSource.Builder(SOURCE_ID)
    .data(samplejson)
    .build()

val symbolLayer = SymbolLayer(CIRLCE_LAYER_ID, SOURCE_ID)

it.addSource(geoJsonSource)
it.addLayer(symbolLayer)
  • 注:

在加载 Mapbox 样式扩展后使用上面的代码,例如:

mapView.getMapboxMap().loadStyle(/* above/your-style-extension*/){ it->//you map style there after they get load

val geoJsonSource = GeoJsonSource.Builder(SOURCE_ID)
    .data(samplejson)
    .build()

val symbolLayer = SymbolLayer(CIRLCE_LAYER_ID, SOURCE_ID)

it.addSource(geoJsonSource)
it.addLayer(symbolLayer)
}


private val RESTROOMS = "RESTROOMS"
private val TRAIL_HEAD = "trailhead"
private val PICNIC_AREA = "PICNIC_AREA"


private val KEY_PICNIC_AREA = "Picnic Area"
private val KEY_RESTROOMS = "Restroom"
private val KEY_TRAIL_HEAD = "Trailhead"
private val ICON_KEY = "POITYPE"
private val TEXT_KEY = "TEXT_KEY"

private val CIRLCE_LAYER_ID = "symbol-layer"
private val SOURCE_ID = "SOURCE_ID"
private val LAYER_ID = "LAYER_ID"

现在,来自 GeoJSON 源的自定义符号和文本将根据 POI 类型显示在地图上。 上述功能 geoJson 将在旧金山展示

© www.soinside.com 2019 - 2024. All rights reserved.