As most of you know, mapbox.addMarker() is deprecated!
I tried to figure the new way to add markers which are using Symbol Layer
I'm using this code, it is working for me! but it re-define the Style of the map every time I want to add a marker
here is the code:
//Add Marker to the Map
public void addMarker(#NonNull LatLng point) {
Feature feature = Feature.fromGeometry(Point.fromLngLat(point.getLongitude(), point.getLatitude()));
mapboxMap
.setStyle(new Style.Builder()
.fromUri("mapbox://styles/mapbox/cjf4m44iw0uza2spb3q0a7s41")
.withImage(ICON_ID, marker)
.withSource(new GeoJsonSource(SOURCE_ID, feature))
.withLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
.withProperties(PropertyFactory.iconImage(ICON_ID),
iconAllowOverlap(true),
iconIgnorePlacement(true),
iconOffset(new Float[]{0f, -9f}))));
}
So, I was wondering if there is a correct or a better way to add markers on the latest MapBox SDK 8.5.0
Thanks!
mapboxMap.setStyle(Style.MAPBOX_STREETS, new Style.OnStyleLoaded() {
#Override
public void onStyleLoaded(#NonNull final Style style) {
AddSanciangkoStreet(style);
SanciangkoStreetMarker();
}
}
private void AddSanciangkoStreet(#NonNull Style style) {
style.addImage("sanciangko-street",
BitmapUtils.getBitmapFromDrawable(getResources().getDrawable(R.drawable.floodicon)));
style.addSource(new GeoJsonSource("sanciangkoFlood1-source-id"));
style.addLayer(new SymbolLayer("sanciangkoFlood1-layer-id", "sanciangkoFlood1-source-id").withProperties(
iconImage("sanciangko-street"),
iconIgnorePlacement(true),
iconAllowOverlap(true),
iconSize(1f)
));
}
private void SanciangkoStreetMarker() {
if (map.getStyle() != null) {
GeoJsonSource sanciangkoFlood1 = map.getStyle().getSourceAs("sanciangkoFlood1-source-id");
if (sanciangkoFlood1 != null) {
sanciangkoFlood1.setGeoJson(FeatureCollection.fromFeature(
Feature.fromGeometry(Point.fromLngLat(123.895801, 10.297237))
));
}
}
}
Related
I have tried many of the solutions that abound here in the forum of the operation of onmarkerclick () but none have worked.
I am working with an app that uses the google maps api and we want to program a route tracer.
The operation that I am trying to achieve now is that by clicking on a marker you can trace the path to it, the problem is that the onmarkerclick method is not working or returning anything.
I will add the 2 parts of the code that I consider important to be able to find the solution to the problem:
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setOnMapClickListener(this);
mMap.setOnMarkerClickListener(this);
mMap.setOnInfoWindowClickListener(this);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
}
else {
buildGoogleApiClient();
mMap.setMyLocationEnabled(true);
}
// Add layer
try {
layer = new KmlLayer(mMap, R.raw.kmltest, getApplicationContext());
layer.addLayerToMap();
// Set a listener for geometry clicked events.
layer.setOnFeatureClickListener(new KmlLayer.OnFeatureClickListener() {
#Override
public void onFeatureClick(Feature feature) {
Log.i("KML", "Feature clicked: " + feature.getProperty("CUA_DESCRI"));
}
});
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// end of layer add
}
public boolean onMarkerClick(Marker marker) {
Log.d("Comprobar markerclick", "onMarkerClick !!!!!!!!!!!!!!!!!! ");
btnTrazarRuta.hide();
//El destino que buscaremos al dar click
destinoRutaUnica = marker.getPosition().latitude + "," + marker.getPosition().longitude;
return false;
}
The onmarkerclick method should hide a button and get the position of the marker, but before that I put a logd to be able to see if it was at least entering the method, but no. It shows absolutely nothing.
Fron anyone who got the same problem.
in my case it was the line:
layer = new KmlLayer(mMap, R.raw.kmltest, getApplicationContext());
apparently, onmarkerclick() and at the same time oninfowindowsclick() stop working when working with a KML layer.
I don't know exactly why.
Once you add a KML layer, it will handle the clicks. You need to instruct the KML layer to delegate the clicks to e.g. your markers or polylines.
here's how to do it with markers (same principle for polylines etc):
MarkerManager markerManager = new MarkerManager(map);
MarkerManager.Collection markerCollection = markerManager.newCollection();
... where map is GoogleMap.
Now when adding a marker to the map
instead of doing:
map.addMarker(markerOptions);
map.setOnMarkerClickListener(listener);
do:
markerCollection.addMarker(markerOptions)
markerCollection.setOnMarkerClickListener(listener);
And now the final hint:
When adding a KML object to the map, pass in the markerManager (and polylineManager etc):
KmlLayer kmlLayer = new KmlLayer(map, R.raw.kmltest, ctxt, markerManager, polygonManager, polylineManager, groundOverlayManager, (cache));
In case you only use markers, it would simply be:
KmlLayer kmlLayer = new KmlLayer(map, R.raw.kmltest, ctxt, markerManager, null, null, null, null);
... and watch ALL your click listeners work
I'm developing an Android app that is supposed to use Google Maps.
I used this code to track the change in zoom
(from here link)
googleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
CameraPosition cameraPosition = googleMap.getCameraPosition();
if(cameraPosition.zoom > 18.0) {
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
} else {
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
}
});
But in this case, the satellite map reloads at the slightest camera shift.
How to load an area of a certain size so that the map does not load continuously?
You need to change map type only if its current type is not what you need. Slightly modify your code to check map type before change it and change only if changes needed:
public class MainActivity extends AppCompatActivity implements OnMapReadyCallback {
private GoogleMap mGoogleMap;
...
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
#Override
public void onCameraMove() {
CameraPosition cameraPosition = mGoogleMap.getCameraPosition();
if(cameraPosition.zoom > 18.0) {
if (mGoogleMap.getMapType() != GoogleMap.MAP_TYPE_HYBRID) {
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
}
} else {
if (mGoogleMap.getMapType() != GoogleMap.MAP_TYPE_NORMAL) {
mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
}
}
});
}
...
}
Firstly I am sorry about my English.
I try to set exact visibile bounds in google maps android api. For example map will only show America's region and user can't scroll map to Canada. When you look to link you can understand what I try to do.I think I can do it with CameraChangeListener and getting visible regions but I couldn't implement algorithm. Can you help me ?
http://sehirharitasi.ibb.gov.tr/
It is not that easy and good as your link but it's something that can work:
//When you setup the map:
map.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
checkBounds();
}
});
And the CheckBounds function can either check if the visible area is inside the allowed one:
public void checkBounds() {
//non ricostruire allowedbounds ogni volta, sono sempre gli stessi, fatti il build nell'onCreate
LatLngBounds actualVisibleBounds = map.getProjection().getVisibleRegion().latLngBounds;
if (allowedBounds.contains(actualVisibleBounds)){
return
}else{
map.animateCamera(CameraUpdateFactory.newLatLngBounds(allowedBounds));
}
}
Or you can use the center of the viewport and check if is inside the allowed area (to allow bounding zooms)
public void checkBounds() {
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(northeast);
builder.include(southwest);
final LatLngBounds allowedBounds = builder.build();
LatLngBounds centro = map.getProjection().getVisibleRegion().latLngBounds;
if (allowedBounds.contains(centro.getCenter()))
return;
else {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(defaultLatLng, zoomLevel));
}
}
i am using following code for creating marker(bitmap),how to add click event for marker. i use graphhopper android for OSM map
startMarker = createMarker(startPoint, R.drawable.marker_departure); layers.add(startMarker);
add use createMarker method
public Marker createMarker(LatLong p, int resource) {
Drawable drawable = activity.getResources().getDrawable(resource);
Bitmap bitmap = AndroidGraphicFactory.convertToBitmap(drawable);
return new Marker(p, bitmap, 0, -bitmap.getHeight() / 2);
}
and how to add text near to marker
thanks in advance
Try with this, may be this will help full.
layers.setOnMarkerClickListener(new OnMarkerClickListener()
{
#Override
public boolean onMarkerClick(Marker arg0) {
//Your stuff
});
i use following code its works for me
MyMarker frommarker = newMyMarker(activity,newLatLong(fl.latitude,fl.longitude), AndroidGraphicFactory.convertToBitmap(activity.getResources().getDrawable(R.drawable.marker_departure)), 0, 0);
mapView.getLayerManager().getLayers().add(frommarker);
and mymarker class
public class MyMarker extends Marker {
private Context ctx;
public MyMarker(Context ctx, LatLong latLong, Bitmap bitmap, int horizontalOffset,
int verticalOffset) {
super(latLong, bitmap, horizontalOffset, verticalOffset);
this.ctx = ctx;
}
#Override
public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) {
if (this.contains(layerXY, tapXY)) {
}
}
I'm trying to display a few points (points of interest) with custom InfoWindow in google maps android. My problem is that I cannot put different information in the different points. I'm facing problems updating the textview content of the popup layout. See my sample code below.
My infoWindowAdapter code:
public class poisInfoWindowAdapter implements InfoWindowAdapter {
#Override
public View getInfoWindow(Marker arg) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
//Get Layout of POI's popups and assign values to text views.
View InfoPopupLayout = getLayoutInflater().inflate(R.layout.infopopup, null);
TextView t = ((TextView)InfoPopupLayout.findViewById(R.id.title));
t.setText(name);
return InfoPopupLayout;
}
}
The code responsable for adding Points to map:
public void onPostExecute(String responsePois) {
try {
JSONArray P = new JSONArray(responsePois);
for (int i = 0; i < P.length(); i++) {
JSONObject pois = P.getJSONObject(i);
position = new LatLng(pois.getDouble("y"), pois.getDouble("x"));
name = pois.getString("name_pt");
Map.setInfoWindowAdapter(new poisInfoWindowAdapter());
Map.addMarker(new MarkerOptions()
.position(position)
.title(name)
);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
In this case all of my points get the same name. The infoWindowAdapter class can't get the correct values from name variable. Anyone knows how to resolve this problem?
I think that what I say and how I explain is understandable but if not, tell me and I will answer.
Thanks
First of all put your Map.setInfoWindowAdapter(new poisInfoWindowAdapter()); outside your for loop in onPostExecute(....)
and second implement your poisInfoWindowAdapter() like below:
public class poisInfoWindowAdapter implements InfoWindowAdapter {
#Override
public View getInfoWindow(Marker arg) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
//Get Layout of POI's popups and assign values to text views.
View InfoPopupLayout = getLayoutInflater().inflate(R.layout.infopopup, null);
TextView t = (TextView)InfoPopupLayout.findViewById(R.id.title);
t.setText(marker.getTitle());
TextView t2 = (TextView)InfoPopupLayout.findViewById(R.id.title2);
t2.setText(marker.getSnippet());
return InfoPopupLayout;
}
}
Update: set Marker as
Currnt = mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.mark_red))
.position(new LatLng(latitude,longitude)
.title(locations)
.snippet(city));