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
Related
I'm using the solution here to add markers to a map in a Fragment and can't figure out why I can only add one marker.
I'm sure I'm missing something when I build the camera position, which is getting called twice in my test code. (See addLocationToMap below).
I am retrieving an ArrayList of geocoordinates on the main thread and want to loop through the list in the map tab calling addLocationToMap on each entry.
Here's my code:
public class RentalMapFragment extends Fragment {
MapView mMapView;
private GoogleMap googleMap;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// inflate and return the layout
View v = inflater.inflate(R.layout.fragment_map, container, false);
mMapView = (MapView) v.findViewById(R.id.mapView);
mMapView.onCreate(savedInstanceState);
mMapView.onResume();// needed to get the map to display immediately
try {
MapsInitializer.initialize(getActivity().getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
googleMap = mMapView.getMap();
int level = 12;
addLocationToMap(17.385044, 78.486679, "Marker 2", level);
addLocationToMap(17.385044, 78.486671, "Marker 1", level);
// Perform any camera updates here
CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(17.385000, 78.486600)).zoom(level).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
return v;
}
private void addLocationToMap(double latitude, double longitude, String markerTitle, int level) {
// Create lat/lon
LatLng latLng = new LatLng(latitude, longitude);
// create marker
MarkerOptions marker = new MarkerOptions().position(latLng).title(markerTitle);
// Changing marker icon
marker.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ROSE));
// adding marker
googleMap.addMarker(marker);
}
#Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
#Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
mMapView.onLowMemory();
}
}
It turns out that I should not be creating the camera position after placing each marker. Rather, after adding all my markers I need to choose a postion for the camera to view the markers from.
I'm updating my question to demonstrate this.
i'm developing my first app and i created the following map viewer activity:
public class MapViewer extends Activity implements OnInfoWindowClickListener, ClusterManager.OnClusterClickListener<MyItem> {
private GoogleMap map;
private LatLng defaultLatLng = new LatLng(X, Y);
private int zoomLevel = 5;
private Database db = new Database(this);
private ClusterManager<MyItem> mClusterManager;
private LatLngBounds allowedBounds;
private final LatLng northeast = new LatLng(A, B);
private final LatLng southwest = new LatLng(C, D);
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mapviewer);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
builder.include(northeast);
builder.include(southwest);
allowedBounds = builder.build();
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);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(defaultLatLng, zoomLevel));
mClusterManager = new ClusterManager<MyItem>(this, map);
mClusterManager.setRenderer(new MyClusterRenderer(this, map, mClusterManager));
mClusterManager.setOnClusterClickListener(this);
map.setOnCameraChangeListener(mClusterManager);
map.setOnMarkerClickListener(mClusterManager);
map.setInfoWindowAdapter(new ClusterInfoWindow(getLayoutInflater()));
map.setOnInfoWindowClickListener(this);
addItems();
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
As you can see i set a listener to map object
map.setOnCameraChangeListener(mClusterManager);
that adds or removes clusters on markers groups, according to zoom level.
Now i would add a listener that checks if user moves on map within some bounds:
map.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
checkBounds();
}
});
But it doesn't work. It works only if i remove the previous listener (mClusterManager).
So, how to make both listener working on the same map object?
Thank you in advance for your replies and sorry for my english.
As there's only a set method and no add method, you can only set one listener at a time. But you could delegate from the one listener to the other like this:
map.setOnCameraChangeListener(new OnCameraChangeListener() {
#Override
public void onCameraChange(CameraPosition cameraPosition) {
checkBounds();
mClusterManager.onCameraChange(cameraPosition);
}
});
Of course mClusterManager does not need to implement the CameraChangeListener interface any more but just needs a method public void onCameraChange(CameraPosition cameraPosition).
How can I add a Tab/Touch/Click listener on the Markers I have on my Google Map in android program. For example in the below image I have one marker on google maps and when clicked, I want to bring up a toast saying this has been clicked
http://i.stack.imgur.com/Bc7Lp.png
I have tried onMapClickListener but that does not work.
map.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng point) {
}
}
All markers in Google Android Maps Api v2 are clickable. You don't need to set any additional properties to your marker. What you need to do - is to register marker click callback to your googleMap and handle click within callback:
public class MarkerDemoActivity extends android.support.v4.app.FragmentActivity
implements OnMarkerClickListener{
private Marker myMarker;
private void setUpMap()
{
.......
googleMap.setOnMarkerClickListener(this);
myMarker = googleMap.addMarker(new MarkerOptions()
.position(latLng)
.title("My Spot")
.snippet("This is my spot!")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
......
}
#Override
public boolean onMarkerClick(final Marker marker) {
if (marker.equals(myMarker))
{
//handle click here
}
}
}
Use this
map.setOnMarkerClickListener(new OnMarkerClickListener()
{
#Override
public boolean onMarkerClick(Marker arg0)
Toast.makeText(MainActivity.this, arg0.getTitle(),1000).show();// display toast
return true;
}
});
This will help to you :)
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;
}
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.