使 Mapbox 标记可点击并 return 标记的 ID
Make Mapbox markers clickable and return the ID of the marker
所以我制作了一个显示 MapBox 地图的地图Activity。
然后我将数据库中的所有标记(图钉,最终是具有经度和纬度的点对象)加载到列表<特征>标记坐标中。然后通过 GeoJsonSource() 给出 markerCoordinates。
现在我所有的标记都显示在地图上了。
现在我不知道如何使标记可点击,点击时我需要获取标记的 ID,以便稍后重定向到另一个 Activity,然后加载 所有 基于该 ID 的数据。此 pin 的 ID 需要与数据库中的 ID 相同。
Mapbox 文档并没有真正帮助我解决这个问题。
有人知道如何实现吗?
MapActivity.java
public class MapActivity extends AppCompatActivity {
private MapView mapView;
DatabaseHelper myDb;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_moments:
Intent intent = new Intent(MapActivity.this, MapActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
break;
case R.id.navigation_addmoment:
Intent intent2 = new Intent(MapActivity.this, AddMomentActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent2);
break;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myDb = new DatabaseHelper(this);
Mapbox.getInstance(this, "pk.eyJ1IjoiaGlqYWNrbWFuaWFjIiwiYSI6ImNqdWlyb3E3NzE5bjc0Zm9lOHpta3AzajMifQ.ithKXW2RvhRzlPqXWBexyg");
setContentView(R.layout.activity_map);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
// Importing markers from database
List<Feature> markerCoordinates = new ArrayList<>();
loadPins(markerCoordinates);
// Adding markers on the map
style.addSource(new GeoJsonSource("source-id",
FeatureCollection.fromFeatures(markerCoordinates)));
// Some styling below
style.addImage("marker-icon-id",
BitmapFactory.decodeResource(
MapActivity.this.getResources(), R.drawable.mapbox_marker_icon_default));
SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
symbolLayer.withProperties(
PropertyFactory.iconImage("marker-icon-id")
);
style.addLayer(symbolLayer);
}
});
}
});
}
// Switch from map to moments
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.header_items, menu);
final MenuItem listItem = menu.findItem(R.id.list_menu);
listItem.setVisible(true);
listItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(MapActivity.this, MomentsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
return true;
}
});
return true;
}
// Reading the Database, appending each row to allMarkers
public void loadPins(List<Feature> allMarkers) {
Cursor res = myDb.getAllData();
if(res.getCount() == 0) {
// Error message
return;
}
while(res.moveToNext()) {
double longitude = Double.parseDouble(res.getString(4));
double latitude = Double.parseDouble(res.getString(5));
if(longitude == 0 || latitude == 0) {
continue;
} else {
allMarkers.add(Feature.fromGeometry(
Point.fromLngLat(
longitude,
latitude
)
));
}
}
}
@Override
public void onStart() {
super.onStart();
mapView.onStart();
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@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);
}
}
首先,您应该实现 onMapClick
或 onMapLongClick
方法,以便您可以处理所有地图点击并检索您需要的数据。
每次点击获取marker Id的步骤大致如下:
检查点击是在标记上还是在其他地方。
您可以通过查询源图层(您的 GeoJsonSource)并检查点击点附近是否有要素来执行此操作。
如果找到某个功能,请获取您需要的 属性。
您可以使用 feature.getProperties()
获取所有属性或使用 feature.getStringProperty("name_of_the_property")
获取特定属性。查看更多 here。
检查此 example 以了解如何实现所有这些。
所以我制作了一个显示 MapBox 地图的地图Activity。
然后我将数据库中的所有标记(图钉,最终是具有经度和纬度的点对象)加载到列表<特征>标记坐标中。然后通过 GeoJsonSource() 给出 markerCoordinates。
现在我所有的标记都显示在地图上了。
现在我不知道如何使标记可点击,点击时我需要获取标记的 ID,以便稍后重定向到另一个 Activity,然后加载 所有 基于该 ID 的数据。此 pin 的 ID 需要与数据库中的 ID 相同。
Mapbox 文档并没有真正帮助我解决这个问题。
有人知道如何实现吗?
MapActivity.java
public class MapActivity extends AppCompatActivity {
private MapView mapView;
DatabaseHelper myDb;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_moments:
Intent intent = new Intent(MapActivity.this, MapActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
break;
case R.id.navigation_addmoment:
Intent intent2 = new Intent(MapActivity.this, AddMomentActivity.class);
intent2.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent2);
break;
}
return false;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myDb = new DatabaseHelper(this);
Mapbox.getInstance(this, "pk.eyJ1IjoiaGlqYWNrbWFuaWFjIiwiYSI6ImNqdWlyb3E3NzE5bjc0Zm9lOHpta3AzajMifQ.ithKXW2RvhRzlPqXWBexyg");
setContentView(R.layout.activity_map);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(@NonNull MapboxMap mapboxMap) {
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
@Override
public void onStyleLoaded(@NonNull Style style) {
// Importing markers from database
List<Feature> markerCoordinates = new ArrayList<>();
loadPins(markerCoordinates);
// Adding markers on the map
style.addSource(new GeoJsonSource("source-id",
FeatureCollection.fromFeatures(markerCoordinates)));
// Some styling below
style.addImage("marker-icon-id",
BitmapFactory.decodeResource(
MapActivity.this.getResources(), R.drawable.mapbox_marker_icon_default));
SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
symbolLayer.withProperties(
PropertyFactory.iconImage("marker-icon-id")
);
style.addLayer(symbolLayer);
}
});
}
});
}
// Switch from map to moments
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.header_items, menu);
final MenuItem listItem = menu.findItem(R.id.list_menu);
listItem.setVisible(true);
listItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
Intent intent = new Intent(MapActivity.this, MomentsActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(intent);
return true;
}
});
return true;
}
// Reading the Database, appending each row to allMarkers
public void loadPins(List<Feature> allMarkers) {
Cursor res = myDb.getAllData();
if(res.getCount() == 0) {
// Error message
return;
}
while(res.moveToNext()) {
double longitude = Double.parseDouble(res.getString(4));
double latitude = Double.parseDouble(res.getString(5));
if(longitude == 0 || latitude == 0) {
continue;
} else {
allMarkers.add(Feature.fromGeometry(
Point.fromLngLat(
longitude,
latitude
)
));
}
}
}
@Override
public void onStart() {
super.onStart();
mapView.onStart();
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
public void onStop() {
super.onStop();
mapView.onStop();
}
@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);
}
}
首先,您应该实现 onMapClick
或 onMapLongClick
方法,以便您可以处理所有地图点击并检索您需要的数据。
每次点击获取marker Id的步骤大致如下:
检查点击是在标记上还是在其他地方。
您可以通过查询源图层(您的 GeoJsonSource)并检查点击点附近是否有要素来执行此操作。
如果找到某个功能,请获取您需要的 属性。
您可以使用
feature.getProperties()
获取所有属性或使用feature.getStringProperty("name_of_the_property")
获取特定属性。查看更多 here。
检查此 example 以了解如何实现所有这些。