I'm using the library Google Maps Utility for Android which allows to create clustering int he maps and I need to show a custom InfoWindow but I can't find any method to do this.
In order to show the info window, I have the following class, and in the method onClusterItemRendered is where I have access to the info of the marker:
class MyClusterRenderer extends DefaultClusterRenderer<MarkerItem> {
public MyClusterRenderer(Context context, GoogleMap map,
ClusterManager<MarkerItem> clusterManager) {
super(context, map, clusterManager);
}
#Override
protected void onBeforeClusterItemRendered(MarkerItem item,
MarkerOptions markerOptions) {
super.onBeforeClusterItemRendered(item, markerOptions);
markerOptions.title(String.valueOf(item.getMarkerId()));
}
#Override
protected void onClusterItemRendered(MarkerItem clusterItem,
Marker marker) {
super.onClusterItemRendered(clusterItem, marker);
}
}
Is there anybody who has used the library and knows how to show a custom InfoWindow such as the way it was used in the Google Maps? Like:
getMap().setInfoWindowAdapter(new InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker arg0) {
return null;
}
});
Yes, this can be done. ClusterManager maintains two MarkerManager.Collections:
one for cluster markers, and
one for individual item markers
You can set a custom InfoWindowAdapter for each of these kinds of markers independently.
Implementation
First, install your ClusterManager's MarkerManager as the map's InfoWindowAdapter:
ClusterManager<MarkerItem> clusterMgr = new ClusterManager<MarkerItem>(context, map);
map.setInfoWindowAdapter(clusterMgr.getMarkerManager());
Next, install your custom InfoWindowAdapter as the adapter for one or both of the marker collections:
clusterMgr.getClusterMarkerCollection().setOnInfoWindowAdapter(new MyCustomAdapterForClusters());
clusterMgr.getMarkerCollection().setOnInfoWindowAdapter(new MyCustomAdapterForItems());
The final piece is mapping the raw Marker object that you'll receive in your custom InfoWindowAdapter's callback to the ClusterItem object(s) that you added to the map in the first place. This can be achieved using the onClusterClick and onClusterItemClick listeners, as follows:
map.setOnMarkerClickListener(clusterMgr);
clusterMgr.setOnClusterClickListener(new OnClusterClickListener<MarkerItem>() {
#Override
public boolean onClusterClick(Cluster<MarkerItem> cluster) {
clickedCluster = cluster; // remember for use later in the Adapter
return false;
}
});
clusterMgr.setOnClusterItemClickListener(new OnClusterItemClickListener<MarkerItem>() {
#Override
public boolean onClusterItemClick(MarkerItem item) {
clickedClusterItem = item;
return false;
}
});
Now you have everything you need to assemble your custom InfoWindow content in your respective Adapters! For example:
class MyCustomAdapterForClusters implements InfoWindowAdapter {
#Override
public View getInfoContents(Marker marker) {
if (clickedCluster != null) {
for (MarkerItem item : clickedCluster.getItems()) {
// Extract data from each item in the cluster as needed
}
}
// build your custom view
// ...
return view;
}
}
So basically you have your class starting like this:
private class MarkerItemClusterRenderer extends
DefaultClusterRenderer<MarkerItem> {
public MarkerItemClusterRenderer(Context context, GoogleMap map,
ClusterManager<MarkerItem> clusterManager) {
...
So in that parameter map of the type GoogleMap is where you have to specify your setInfoWindowAdapter.
Related
I have a DefaultClusterRenderer class and my own ClusterItem, which I am using as marker on the map. I am setting the title and snippet with MarkerOptions, so I can grap them on my onInfoWindowClick event. I wanna start a new Activity, depends on which infoWindow the user clicked, but I cant add a tag to MarkerOptions, so I cant get the tag in my onInfoWindowClick method via the Marker parameter.
I am looking for a good solution to add an id to each ClusterItem and get the id via Marker in onInfoWindowClick.
public class OwnClusterRendering extends DefaultClusterRenderer<GeoPoint> {
private GoogleMap map;
public OwnClusterRendering(Context context, GoogleMap map, ClusterManager<GeoPoint> clusterManager) {
super(context, map, clusterManager);
this.map = map;
}
protected void onBeforeClusterItemRendered(GeoPoint geoPoint, MarkerOptions markerOptions) {
markerOptions.icon(geoPoint.getIcon());
markerOptions.snippet(geoPoint.getSnippet());
markerOptions.title(geoPoint.getTitle());
super.onBeforeClusterItemRendered(geoPoint, markerOptions);
}
}
MyCustomWindowAdapter:
#Override
public void onInfoWindowClick(Marker marker) {
Log.d("test", marker.getTitle());
Log.d("test", marker.getSnippet());
Log.d("test", marker.getId());
Log.d("test", String.valueOf(marker.getTag()));
// Intent intent = new Intent(context, StoneInfoSliderActivity.class);
// context.startActivity(intent);
}
Solved it with the following method from DefaultClusterRenderer<>
#Override
protected void onClusterItemRendered(GeoPoint geoPoint, Marker marker) {
marker.setTag(geoPoint.getId());
super.onClusterItemRendered(geoPoint, marker);
}
I want to change the icon of a map marker only while it's selected.
I implemented GoogleMap.OnMarkerClickListener class in my Fragment class.
public class MapFragment extends SupportMapFragment implements GoogleMap.OnMarkerClickListener{
....
#Override
public boolean onMarkerClick(Marker marker) {
marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.placemarker_pressed));
return false;
}
}
It changes the marker icon when clicked. How can I set it back to the original icon when it's unselected?
Implement also the GoogleMap.OnMapClickListener interface and create a private variable to store the current selected marker:
private Marker mSelectedMarker;
Then:
#Override
public boolean onMarkerClick(Marker marker) {
if (null != mSelectedMarker) {
mSelectedMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.placemarker));
}
mSelectedMarker = marker;
mSelectedMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.placemarker_pressed));
return false;
}
#Override
public boolean onMapClick(LatLng latLng) {
if(null != mSelectedMarker) {
mSelectedMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.placemarker));
}
mSelectedMarker = null;
}
This question already has answers here:
Android Maps Utils Clustering show InfoWindow
(3 answers)
Closed 4 years ago.
i'm developing my app that use markers on google map. Then i use clustering to gather markers that are too closer. Here is part of my code:
MapViewer.java
public class MapViewer extends Activity implements OnInfoWindowClickListener {
private GoogleMap map;
private ClusterManager<MyItem> mClusterManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapviewer);
try {
map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
if (map != null) {
map.setMyLocationEnabled(true);
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
map.getUiSettings().setRotateGesturesEnabled(false);
mClusterManager = new ClusterManager<MyItem>(this, map);
mClusterManager.setRenderer(new MyClusterRenderer(this, map, mClusterManager));
map.setOnCameraChangeListener(mClusterManager);
map.setOnMarkerClickListener(mClusterManager);
map.setInfoWindowAdapter(new ClusterInfoWindow(getLayoutInflater()));
map.setOnInfoWindowClickListener(this);
addItems();
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
#Override
public void onInfoWindowClick(Marker marker) {
// My code
}
public void addItems() {
// My code
}
}
ClusterInfoWindow.java
public class ClusterInfoWindow implements InfoWindowAdapter {
LayoutInflater inflater = null;
public ClusterInfoWindow(LayoutInflater inflater) {
this.inflater = inflater;
}
#Override
public View getInfoWindow(Marker marker) {
return(null);
}
#Override
public View getInfoContents(Marker marker) {
View popup = inflater.inflate(R.layout.infowindow, null);
TextView tv = (TextView)popup.findViewById(R.id.title);
tv.setText(marker.getTitle());
tv = (TextView)popup.findViewById(R.id.snippet);
tv.setText(marker.getSnippet());
return(popup);
}
}
If i click on single marker it shows a popup with some details. The same happens if i click on a cluster. How to make the cluster not clickable? I don't want to show anything when user click on cluster.
Thank you.
Based on the documentation from Google Maps:
If you want to add specific functionality in response to a marker click event, set the map's OnMarkerClickListener() to the ClusterManager, since ClusterManager implements the listener.
So, instead of doing map.setOnMarkerClickListener(mClusterManager); you can change it to the following:
map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
return false;
}
});
You want to implement ClusterManager.OnClusterItemClickListener or ClusterManager.OnClusterItemInfoWindowClickListener
I have an activity that holds a fragment with Google Map view in it. App adds several dozens of markers to the MapView, using MarkerManager and ClusterRenderer to form clusters.
The problem is that when I have marker's InfoWindow opened and I press hardware Back button, it closes the app. Instead of that, I would like to have the InfoWindow closed.
Is there any straightforward way to achieve this?
I managed to solve the problem.
I modified MarkerManager to send notification via EventBus when InfoWindow is about to be opened:
#Override
public View getInfoContents(Marker marker) {
View content = fillContent();
EventBus.getDefault().post(new MapInfoWindowShownEvent(marker));
return content;
}
and I added event handling in the activity:
private Marker mLastShownInfoWindowMarker = null;
#Override
public void onBackPressed() {
if(mLastShownInfoWindowMarker != null && mLastShownInfoWindowMarker.isInfoWindowShown()) {
mLastShownInfoWindowMarker.hideInfoWindow();
} else {
super.onBackPressed();
}
}
public void onEvent(MapInfoWindowShownEvent event) {
mLastShownInfoWindowMarker = event.getMarker();
}
Using this information I decided to make it a bit simpler for myself:
private Marker mLastShownInfoWindowMarker = null;
public void setMLastShownInfoWindowMarker(Marker marker)
{this.mActiveMapMarker=marker;}
#Override
public void onBackPressed() {
if(mLastShownInfoWindowMarker != null && mLastShownInfoWindowMarker.isInfoWindowShown()) {
mLastShownInfoWindowMarker.hideInfoWindow();
} else {
super.onBackPressed();
}
}
Then the following where you have your mapfragment:
private MainActivity activity; // swap this to your activity
public MainActivityMapController(MainActivity activity) {
this.activity = activity;
}
// override markerclicklistener to store lastShownInfoWindowMarker in
// the activity where back button will be used
map.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
activity.setMLastShownInfoWindowMarker(marker);
return false; // false keeps the standard behavior
}
});
I'm using Google Maps Android API Utility Library in order to show several markers in a map in a clustered way.
I've followed the instructions to make it work, as well as taking a look at the examples in the library, but I can't figure out how to show an InfoWindow when a marker is clicked.
I guess getMap().setOnMarkerClickListener(mClusterManager); is the one managing the onClick events, and if commented out, I can override it using getMap().setInfoWindowAdapter(new InfoWindowAdapter() {)); but I have no access to my custom marker object.
Nevertheless, if I use getMap().setOnMarkerClickListener(mClusterManager);, I can't find a way to show the InfoWindow when a marker has been clicked.
Does anybody have any idea about how to achieve this?
Thanks a lot in advance!
You need to extend the DefaultClusterRenderer class and override the onBeforeClusterItemRendered, attaching the title to the MarkerOptions object passed as argument.
After that, you can pass your implementation to the ClusterManager.
Example:
class MyItem implements ClusterItem {
private LatLng mPosition;
private String mTitle;
public MyItem(LatLng position){
mPosition = position;
}
#Override
public LatLng getPosition() {
return mPosition;
}
public String getTitle() {
return mTitle;
}
public void setTitle(String title) {
mTitle = title;
}
}
class MyClusterRenderer extends DefaultClusterRenderer<MyItem> {
public MyClusterRenderer(Context context, GoogleMap map,
ClusterManager<MyItem> clusterManager) {
super(context, map, clusterManager);
}
#Override
protected void onBeforeClusterItemRendered(MyItem item, MarkerOptions markerOptions) {
super.onBeforeClusterItemRendered(item, markerOptions);
markerOptions.title(item.getTitle());
}
#Override
protected void onClusterItemRendered(MyItem clusterItem, Marker marker) {
super.onClusterItemRendered(clusterItem, marker);
//here you have access to the marker itself
}
}
And then you can use it in this way:
ClusterManager<MyItem> clusterManager = new ClusterManager<MyItem>(this, getMap());
clusterManager.setRenderer(new MyClusterRenderer(this, getMap() ,clusterManager));