【问题标题】:Android Maps Utils Clustering show InfoWindowAndroid Maps Utils Clustering 显示 InfoWindow
【发布时间】:2015-09-06 14:55:50
【问题描述】:

我打算使用 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();
    }

}

【问题讨论】:

  • 看起来这可能会有所帮助:stackoverflow.com/questions/25968486/…
  • @DanielNugent 据我了解,你给我的链接解释了如何将 InfoWindow 添加到整个集群。单击它时,我想在单个标记上显示一个普通的信息窗口,就像普通的谷歌地图一样

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


【解决方案1】:

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

此解决方案只为标记实现 InfoWindows。

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

请注意,由于所有数据都存储在 MyItem 引用中,因此扩展功能以在信息窗口中为每个标记显示任意数量的数据类型要容易得多。

首先是 MyItem.java,其中包括 Title 和 Snippet 的额外字段:

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 上添加了对处理点击事件的支持,使 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;
        }
    }
}

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>

结果:

首次发布:

缩小,开始聚类:

再次缩小,更多聚类:

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

然后点击另一个标记:

编辑:为了在自定义信息窗口周围显示“语音气泡”,请使用 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;
    }
}

结果:

【讨论】:

  • 非常感谢您的出色回答! :) 我如何像普通的 InfoWindow 一样在 InfoWindow 下方添加小向下箭头?另外我将如何添加 onInfoWindowClickListener?就像我使用法线贴图一样?
  • @qwertz 我得调查一下!点击信息窗口,我会让它工作并更新答案!
  • @qwertz 我刚刚让 InfoWindow 点击处理工作,并将更新的代码添加到答案中。查看带有added 注释的代码行,以及类定义和新的覆盖方法onClusterItemInfoWindowClick()
  • 非常感谢!是否可以在信息窗口底部添加语音气泡箭头?
  • @qwertz 我还需要调查一下,如果我发现任何东西,我一定会更新你!我不确定为什么它不存在,我需要做一些研究。
【解决方案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();
    }

【讨论】:

  • 我是否必须在 MyItem 类中添加标题和 sn-p 字段?如何为标记添加标题和 sn-p?
  • 我想,你得加上title和sn-p
【解决方案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("");
            }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-10
    • 2016-09-17
    • 2011-05-16
    • 2023-03-17
    • 2016-12-29
    • 2020-02-17
    • 1970-01-01
    • 2014-02-13
    相关资源
    最近更新 更多