java - Android Maps Utils Clustering show InfoWindow

标签 java android google-maps google-maps-markers infowindow

我打算使用 utils 库中可用的 google maps 标记聚类,但 google 示例应用程序只显示标记聚类而没有任何 infoWindow。我现在想知道,我不能显示信息窗口吗?我希望 InfoWindow 像普通的谷歌地图标记一样显示在标记上,而不是在集群上。

我的代码:(来自谷歌示例)

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();
    }

}

最佳答案

这是一个基于 this answer 的简化且稍作修改的解决方案.请注意,链接的答案为标记和集群实现了一个信息窗口。

此解决方案仅实现 InfoWindows for Markers。

这类似于您为没有聚类的普通标记实现自定义 InfoWindowAdapter 的方式,但额外的要求是您保留对当前选定项目的引用,以便您可以从它的 MyItem 中获取标题和 fragment 实例,因为标记不像通常那样存储标题和代码段。

请注意,由于所有数据都存储在 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 类,其中包括为使用 Cluster 库添加的每个标记支持 InfoWindows 的所有功能:

编辑:添加了对处理 InfoWindow 上的点击事件的支持,使 Activity 实现 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;
        }
    }
}

信息窗口.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>

结果:

初始启动:

enter image description here

缩小,开始聚类:

enter image description here

再次缩小,更多聚类:

enter image description here

然后,放大并单击单个标记:

enter image description here

然后点击另一个标记:

enter image description here

编辑:为了在自定义 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;
    }
}

结果:

enter image description here

关于java - Android Maps Utils Clustering show InfoWindow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30958224/

相关文章:

ios - swift - 如何在应用程序运行时顺利加载谷歌地图 View

java - jackson 解析器 : ignore deserializing for type mismatch

java8 lambda : convert a String of 0's and 1' s to basic array of booleans

java - 60 秒后停止异步任务

android - getActionBar() 应该返回 null 吗?

android-如何在谷歌地图上将标记的位置显示为地址

java - 加载图像时出现内存不足错误

java - 在 HashMap Key 中输入 3 个属性

android - 构建 flutter com.android.builder.internal.aapt.v2.Aapt2Exception : Android resource linking failed

android - Google map Android API v2 - 简单的 map 应用程序崩溃