Android

Android Maps Utils Clustering show InfoWindow

Android Maps Utils показывает кластеризацию InfoWindow

Я планирую использовать кластеризацию маркеров Google Maps, доступную в библиотеке utils, но приложение Google example показывает только кластеры маркеров без какого-либо InfoWindow. Теперь мне интересно, не могу ли я отобразить 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();
}

}
Переведено автоматически
Ответ 1

Вот упрощенное и слегка измененное решение, основанное на этом ответе. Обратите внимание, что связанный ответ реализует 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, который включает в себя все функциональные возможности для поддержки InfoWindows для каждого маркера, добавленного с помощью библиотеки кластеров:

Редактировать: Добавлена поддержка обработки событий щелчка в 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>

Результат:

Первоначальный запуск:

введите описание изображения здесь

При уменьшении масштаба запускается кластеризация:

введите описание изображения здесь

Снова уменьшите масштаб, больше кластеризации:

введите описание изображения здесь

Then, zooming in, and clicking on an individual Marker:

enter image description here

Then clicking on another Marker:

введите описание изображения здесь

Редактировать: Чтобы отобразить "речевой пузырь" вокруг пользовательского 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;
}
}

Результат:

введите описание изображения здесь

Ответ 2
  @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();
}
Ответ 3

Вы могли бы рассмотреть следующий подход:

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("");
}
java android google-maps