Android Maps Utils Clustering show InfoWindow

前端 未结 3 1612
天命终不由人
天命终不由人 2020-11-30 06:17

I am planning to use the google maps marker clustering available in the utils library, but the google example app only shows marker clusters without any infoWindow. I am won

相关标签:
3条回答
  • 2020-11-30 06:52

    Here is a simplified and slightly modified solution based on this answer. Note that the linked answer implements an InfoWindow for both Markers and Clusters.

    This solution only implements InfoWindows for Markers.

    It's similar to how you would implement a custom InfoWindowAdapter for normal Markers with no Clustering, but with the additional requirement that you keep a reference to the currently selected Item so that you can get the Title and Snippet from it's MyItem instance, since the Marker does not store the Title and Snippet as it usually does.

    Note that since all of the data is stored in MyItem references, it's much easier to extend the functionality to display as many data types as you want in the InfoWindow for each Marker.

    First, the MyItem.java, which includes extra fields for Title and 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;
        }
    }
    

    Here is the full Activity class, which includes all of the functionality to support InfoWindows for each Marker added using the Cluster library:

    Edit: Added support for handling click events on the InfoWindow, made the Activity implement OnClusterItemInfoWindowClickListener and added the onClusterItemInfoWindowClick callback.

    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>
    

    Result:

    Initial launch:

    enter image description here

    Zooming out, starts Clustering:

    enter image description here

    Zooming out again, more Clustering:

    enter image description here

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

    enter image description here

    Then clicking on another Marker:

    enter image description here

    Edit: In order to show the "speech bubble" around the custom InfoWindow, use getInfoContents() instead of 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;
        }
    }
    

    Result:

    enter image description here

    0 讨论(0)
  • 2020-11-30 06:52

    You could consider the following approach:

    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("");
                }
    
    0 讨论(0)
  • 2020-11-30 06:53
      @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();
        }
    
    0 讨论(0)
提交回复
热议问题