Android карты Utils кластеризация показать InfoWindow
Я планирую использовать маркерную кластеризацию google maps, доступную в библиотеке utils, но приложение Google example показывает только маркерные кластеры без какого-либо infoWindow. Мне вот интересно, я не смогла показать InfoWindow? Я хочу, чтобы информационное окно отображалось на маркере, как при обычном маркере google maps, а не на кластере.
Код у меня есть: (из примера 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();
}
}
3 ответа:
Вот упрощенное и слегка модифицированное решение, основанное наэтом ответе . Обратите внимание, что связанный ответ реализует InfoWindow как для маркеров, так и для кластеров.
Это решение реализует только InfoWindows для маркеров.
Это похоже на то, как вы бы реализовали пользовательский InfoWindowAdapter для обычных маркеров без кластеризации, но с дополнительным требованием, чтобы вы сохраняли ссылку на текущий выбранный элемент, чтобы вы могли получить заголовок и Фрагмент из его экземпляра
MyItem
, так как маркер не хранит заголовок и фрагмент, как это обычно делается.Обратите внимание, что поскольку все данные хранятся в ссылках
MyItem
, гораздо проще расширить функциональность, чтобы отобразить столько типов данных, сколько вы хотите в окне InfoWindow для каждого маркера.Во-первых, MyItem.java, которая включает дополнительные поля для заголовка и сниппета:
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; } }
Вот полный класс Activity, который включает в себя все функции для поддержки Информационные окна для каждого маркера, добавленного с помощью библиотеки кластеров:
Edit: добавлена поддержка обработки событий click в InfoWindow, реализована реализация действия
OnClusterItemInfoWindowClickListener
и добавлен обратный вызов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>
Результат:
Начальный запуск:
Уменьшение масштаба, начинается кластеризация:
Масштабирование снова, больше кластеризации:
Затем увеличьте масштаб и нажмите кнопку на отдельном маркере:
Затем щелчок по другому маркеру:
Edit: чтобы показать "речевой пузырь" вокруг пользовательского InfoWindow, используйте
getInfoContents()
вместо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; } }
Результат:
@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(); }
Можно рассмотреть следующий подход:
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(""); }