Android Maps Utils Clustering show InfoWindow
google-maps google-maps-markers (3)
Aquí hay una solución simplificada y ligeramente modificada basada en esta respuesta . Tenga en cuenta que la respuesta vinculada implementa una ventana de información tanto para marcadores como para clústeres.
Esta solución solo implementa InfoWindows para marcadores.
Es similar a cómo implementaría un InfoWindowAdapter personalizado para marcadores normales sin agrupamiento, pero con el requisito adicional de que mantenga una referencia al elemento seleccionado actualmente para que pueda obtener el título y el
MyItem
instancia
MyItem
, ya que el marcador sí no almacene el Título y el Fragmento como generalmente lo hace.
Tenga en cuenta que, dado que todos los datos se almacenan en referencias de
MyItem
, es mucho más fácil ampliar la funcionalidad para mostrar tantos tipos de datos como desee en la ventana de información para cada marcador.
Primero, MyItem.java, que incluye campos adicionales para Título y Fragmento:
public class MyItem implements ClusterItem {
private final LatLng mPosition;
private final String mTitle;
private final String mSnippet;
public MyItem(double lat, double lng, String t, String s) {
mPosition = new LatLng(lat, lng);
mTitle = t;
mSnippet = s;
}
@Override
public LatLng getPosition() {
return mPosition;
}
public String getTitle(){
return mTitle;
}
public String getSnippet(){
return mSnippet;
}
}
Aquí está la clase de actividad completa, que incluye toda la funcionalidad para admitir InfoWindows para cada marcador agregado mediante la biblioteca de clúster:
Editar: Se agregó soporte para manejar eventos de clic en InfoWindow, hizo que la actividad implementara
OnClusterItemInfoWindowClickListener
y agregó la
onClusterItemInfoWindowClick
llamada
onClusterItemInfoWindowClick
.
public class MapsActivity extends AppCompatActivity
implements ClusterManager.OnClusterItemInfoWindowClickListener<MyItem> {
private ClusterManager<MyItem> mClusterManager;
private MyItem clickedClusterItem;
private GoogleMap mMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
setUpMapIfNeeded();
}
@Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
mMap.getUiSettings().setMapToolbarEnabled(true);
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.setMyLocationEnabled(true);
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
mClusterManager = new ClusterManager<>(this, mMap);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.779977,-122.413742), 10));
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setOnMarkerClickListener(mClusterManager);
mMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());
mMap.setOnInfoWindowClickListener(mClusterManager); //added
mClusterManager.setOnClusterItemInfoWindowClickListener(this); //added
mClusterManager
.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener<MyItem>() {
@Override
public boolean onClusterItemClick(MyItem item) {
clickedClusterItem = item;
return false;
}
});
addItems();
mClusterManager.getMarkerCollection().setOnInfoWindowAdapter(
new MyCustomAdapterForItems());
}
private void addItems() {
double latitude = 37.779977;
double longitude = -122.413742;
for (int i = 0; i < 10; i++) {
double offset = i / 60d;
double lat = latitude + offset;
double lng = longitude + offset;
MyItem offsetItem = new MyItem(lat, lng, "title " + i+1, "snippet " + i+1);
mClusterManager.addItem(offsetItem);
}
}
//added with edit
@Override
public void onClusterItemInfoWindowClick(MyItem myItem) {
//Cluster item InfoWindow clicked, set title as action
Intent i = new Intent(this, OtherActivity.class);
i.setAction(myItem.getTitle());
startActivity(i);
//You may want to do different things for each InfoWindow:
if (myItem.getTitle().equals("some title")){
//do something specific to this InfoWindow....
}
}
public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {
private final View myContentsView;
MyCustomAdapterForItems() {
myContentsView = getLayoutInflater().inflate(
R.layout.info_window, null);
}
@Override
public View getInfoWindow(Marker marker) {
TextView tvTitle = ((TextView) myContentsView
.findViewById(R.id.txtTitle));
TextView tvSnippet = ((TextView) myContentsView
.findViewById(R.id.txtSnippet));
tvTitle.setText(clickedClusterItem.getTitle());
tvSnippet.setText(clickedClusterItem.getSnippet());
return myContentsView;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
}
}
info_window.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="20dp"
android:orientation="vertical"
android:background="#000000">
<TextView
android:id="@+id/txtTitle"
android:textColor="#D3649F"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/txtSnippet"
android:textColor="#D3649F"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Resultado:
Lanzamiento inicial:
Al alejarse, comienza la agrupación:
Alejando de nuevo, más agrupamiento:
Luego, acercar y hacer clic en un marcador individual:
Luego haciendo clic en otro marcador:
Editar: para mostrar el "globo de diálogo" alrededor de la ventana de información personalizada, use
getInfoContents()
lugar de
getInfoWindow()
:
public class MyCustomAdapterForItems implements GoogleMap.InfoWindowAdapter {
private final View myContentsView;
MyCustomAdapterForItems() {
myContentsView = getLayoutInflater().inflate(
R.layout.info_window, null);
}
@Override
public View getInfoWindow(Marker marker) {
return null;
}
@Override
public View getInfoContents(Marker marker) {
TextView tvTitle = ((TextView) myContentsView
.findViewById(R.id.txtTitle));
TextView tvSnippet = ((TextView) myContentsView
.findViewById(R.id.txtSnippet));
tvTitle.setText(clickedClusterItem.getTitle());
tvSnippet.setText(clickedClusterItem.getSnippet());
return myContentsView;
}
}
Resultado:
Estoy planeando usar el grupo de marcadores de Google Maps disponible en la biblioteca de utilidades, pero la aplicación de ejemplo de Google solo muestra grupos de marcadores sin ninguna ventana de información. Me pregunto ahora, ¿no puedo mostrar una ventana de información? Quiero que la ventana de información se muestre en el marcador como con un marcador de Google Maps normal, no en el clúster.
El código que tengo: (Del ejemplo de google)
public class BigClusteringDemoActivity extends FragmentActivity {
private ClusterManager<MyItem> mClusterManager;
private GoogleMap mMap;
private void readItems() {
InputStream inputStream = getResources().openRawResource(R.raw.radar_search);
List<MyItem> items = new MyItemReader().read(inputStream);
for (int i = 0; i < 10; i++) {
double offset = i / 60d;
for (MyItem item : items) {
LatLng position = item.getPosition();
double lat = position.latitude + offset;
double lng = position.longitude + offset;
MyItem offsetItem = new MyItem(lat, lng);
mClusterManager.addItem(offsetItem);
}
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
mClusterManager = new ClusterManager<>(this, mMap);
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));
mMap.setOnCameraChangeListener(mClusterManager);
readItems();
}
}
Podría considerar el siguiente enfoque:
public void initilizeMap() {
googleMap = mFragment.getMap();
googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
googleMap.getUiSettings().setZoomControlsEnabled(true`enter code here`); // true to`enter code here`
googleMap.getUiSettings().setZoomGesturesEnabled(true);
googleMap.getUiSettings().setCompassEnabled(true);
googleMap.getUiSettings().setMyLocationButtonEnabled(true);
googleMap.getUiSettings().setRotateGesturesEnabled(true);
if (googleMap == null) {
Toast.makeText(getActivity(), "Sorry! unable to create maps",
Toast.LENGTH_SHORT).show();
}
mClusterManager = new ClusterManager<MyItem>(getActivity(), googleMap );
// googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter());
googleMap.setOnMapLoadedCallback(this);
googleMap.setMyLocationEnabled(true);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setTiltGesturesEnabled(true);
MyItem offsetItem = new MyItem(Double.parseDouble(outletList.get(i).getMap_latitude()),
Double.parseDouble(outletList.get(i).getMap_longitude()), title , address);
mClusterManager.addItem(offsetItem);
googleMap.setInfoWindowAdapter(new CustomInfoWindowAdapter(offsetItem));
}
private class CustomInfoWindowAdapter implements InfoWindowAdapter {
Marker marker;
private View view;
private MyItem items;
public CustomInfoWindowAdapter(MyItem item) {
view = getActivity().getLayoutInflater().inflate(
R.layout.custom_info_window, null);
this.items = item;
}
@Override
public View getInfoContents(Marker marker) {
if (marker != null && marker.isInfoWindowShown()) {
marker.hideInfoWindow();
marker.showInfoWindow();
}
return null;
}
@Override
public View getInfoWindow(final Marker marker) {
this.marker = marker;
String url = null;
if (marker.getId() != null && markers != null && markers.size() > 0) {
if (markers.get(marker.getId()) != null
&& markers.get(marker.getId()) != null) {
url = markers.get(marker.getId());
}
}
final ImageView image = ((ImageView) view.findViewById(R.id.badge));
if (url != null && !url.equalsIgnoreCase("null")
&& !url.equalsIgnoreCase("")) {
imageLoader.displayImage(url, image, options,
new SimpleImageLoadingListener() {
@Override
public void onLoadingComplete(String imageUri,
View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view,
loadedImage);
getInfoContents(marker);
}
});
} else {
image.setImageResource(R.drawable.ic_launcher);
}
final String title = items.getTitle();
Log.e(TAG, "TITLE : "+title);
final TextView titleUi = ((TextView) view.findViewById(R.id.title));
if (title != null) {
titleUi.setText(title);
} else {
titleUi.setText("");
}
final String address = items.getAddress();
final TextView snippetUi = ((TextView) view
.findViewById(R.id.snippet));
if (address != null) {
snippetUi.setText(address);
} else {
snippetUi.setText("");
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
mClusterManager = new ClusterManager<>(this, mMap);
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10));
mMap.setOnCameraChangeListener(mClusterManager);
mMap.setInfoWindowAdapter(new InfoWindowAdapter() {
/**
* View for displaying marker popup, if null default framework view would be used
*/
@Override
public View getInfoWindow(Marker marker) {
return null;
}
/**
* For changing the content of infowindow
* Called when showMarkerInfo method is called
*/
@Override
public View getInfoContents(Marker marker) {
View v = getLayoutInflater().inflate(R.layout.view_to_inflate, null);
//code for initializing view part
return v;
}
});
readItems();
}