@Override /** * - Capture the clicked cluster so we can use it in custom infoWindow - Check overall bounds of * items in cluster - If the bounds are empty (all hosts at same place) then let it pop the info * window - Otherwise, move the camera to show the bounds of the map */ public boolean onClusterClick(Cluster<HostBriefInfo> cluster) { mLastClickedCluster = cluster; // remember for use later in the Adapter // Find out the bounds of the hosts currently in cluster LatLngBounds.Builder builder = new LatLngBounds.Builder(); for (HostBriefInfo host : cluster.getItems()) { builder.include(host.getLatLng()); } LatLngBounds bounds = builder.build(); // If the hosts are not all at the same location, then change bounds of map. if (!bounds.southwest.equals(bounds.northeast)) { // Offset from edge of map in pixels when exploding cluster View mapView = findViewById(R.id.map_fragment); int padding_percent = getResources().getInteger(R.integer.cluster_explode_padding_percent); int padding = Math.min(mapView.getHeight(), mapView.getWidth()) * padding_percent / 100; CameraUpdate cu = CameraUpdateFactory.newLatLngBounds( bounds, mapView.getWidth(), mapView.getHeight(), padding); mMap.animateCamera(cu); return true; } showMultihostSelectDialog((ArrayList<HostBriefInfo>) cluster.getItems()); return true; }
@Override public boolean onClusterClick(Cluster<MarkerData> cluster) { String firstName = cluster.getItems().iterator().next().getName(); Toast.makeText(this, cluster.getSize() + " (including " + firstName + ")", Toast.LENGTH_SHORT) .show(); return true; }
@Override public boolean onClusterClick(Cluster<MyItem> cluster) { Collection<MyItem> collection = cluster.getItems(); showIconDialog(collection); return true; }
@Override /** Start the Search tab with the members we have at this exact location. */ public void onClusterInfoWindowClick(Cluster<HostBriefInfo> hostBriefInfoCluster) { Intent intent = new Intent(this, ListSearchTabActivity.class); intent.putParcelableArrayListExtra( "search_results", (ArrayList<HostBriefInfo>) hostBriefInfoCluster.getItems()); startActivity(intent); }
/** * Attempt to determine the location status of items in the cluster, whether all in one location * or in a variety of locations. * * @param cluster * @return */ protected ClusterStatus clusterLocationStatus(Cluster<HostBriefInfo> cluster) { HashSet<String> latLngs = new HashSet<String>(); for (HostBriefInfo item : cluster.getItems()) { latLngs.add(item.getLatLng().toString()); } // if cluster size and latLngs size are same, all are unique locations, so 'none' if (cluster.getSize() == latLngs.size()) { return ClusterStatus.none; } // If there is only one unique location, then all are in same location. else if (latLngs.size() == 1) { return ClusterStatus.all; } // Otherwise it's a mix of same and other location return ClusterStatus.some; }
private void perform(MarkerModifier markerModifier) { // Don't show small clusters. Render the markers inside, instead. if (!shouldRenderAsCluster(cluster)) { for (T item : cluster.getItems()) { Marker marker = mMarkerCache.get(item); MarkerWithPosition markerWithPosition; if (marker == null) { MarkerOptions markerOptions = new MarkerOptions(); if (animateFrom != null) { markerOptions.position(animateFrom); } else { markerOptions.position(item.getPosition()); } onBeforeClusterItemRendered(item, markerOptions); marker = mClusterManager.getMarkerCollection().addMarker(markerOptions); markerWithPosition = new MarkerWithPosition(marker); mMarkerCache.put(item, marker); if (animateFrom != null) { markerModifier.animate(markerWithPosition, animateFrom, item.getPosition()); } } else { markerWithPosition = new MarkerWithPosition(marker); } onClusterItemRendered(item, marker); newMarkers.add(markerWithPosition); } return; } MarkerOptions markerOptions = new MarkerOptions().position(animateFrom == null ? cluster.getPosition() : animateFrom); onBeforeClusterRendered(cluster, markerOptions); Marker marker = mClusterManager.getClusterMarkerCollection().addMarker(markerOptions); mMarkerToCluster.put(marker, cluster); mClusterToMarker.put(cluster, marker); MarkerWithPosition markerWithPosition = new MarkerWithPosition(marker); if (animateFrom != null) { markerModifier.animate(markerWithPosition, animateFrom, cluster.getPosition()); } onClusterRendered(cluster, marker); newMarkers.add(markerWithPosition); }
/** * Gets the "bucket" for a particular cluster. By default, uses the number of points within the * cluster, bucketed to some set points. */ protected int getBucket(Cluster<T> cluster) { int size = cluster.getSize(); if (size <= BUCKETS[0]) { return size; } for (int i = 0; i < BUCKETS.length - 1; i++) { if (size < BUCKETS[i + 1]) { return BUCKETS[i]; } } return BUCKETS[BUCKETS.length - 1]; }
@Override protected boolean shouldRenderAsCluster(Cluster<HostBriefInfo> cluster) { // Render as a cluster if all the items are at the exact same location, or if there are more // than // min_cluster_size in the cluster. ClusterStatus status = clusterLocationStatus(cluster); boolean renderAsCluster = status == ClusterStatus.all || status == ClusterStatus.some || cluster.getSize() >= getResources().getInteger(R.integer.min_cluster_size); return renderAsCluster; }
@Override protected void onBeforeClusterRendered( Cluster<MarkerData> cluster, MarkerOptions markerOptions) { super.onBeforeClusterRendered(cluster, markerOptions); List<Drawable> profilePhotos = new ArrayList<Drawable>(Math.min(4, cluster.getSize())); int width = dimension; int height = dimension; for (MarkerData markerData : cluster.getItems()) { // Draw 4 at most. if (profilePhotos.size() == 4) break; Drawable drawable = ContextCompat.getDrawable(getApplicationContext(), markerData.getProfilePhoto()); // getResources().getDrawable(markerData.getProfilePhoto()); drawable.setBounds(0, 0, width, height); profilePhotos.add(drawable); } MultiDrawable multiDrawable = new MultiDrawable(profilePhotos); multiDrawable.setBounds(0, 0, width, height); clusterImageView.setImageDrawable(multiDrawable); Bitmap icon = clusterIconGenerator.makeIcon(String.valueOf(cluster.getSize())); markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)); }
@Override protected void onBeforeClusterRendered( Cluster<HostBriefInfo> cluster, MarkerOptions markerOptions) { if (clusterLocationStatus(cluster) == ClusterStatus.all) { int size = cluster.getSize(); BitmapDescriptor descriptor = mIcons.get(size); if (descriptor == null) { // Cache new bitmaps descriptor = BitmapDescriptorFactory.fromBitmap( mSingleLocationClusterIconGenerator.makeIcon(String.valueOf(size))); mIcons.put(size, descriptor); } markerOptions.icon(descriptor); } else { super.onBeforeClusterRendered(cluster, markerOptions); } }
@Override public boolean onClusterClick(Cluster<Case> cluster) { float zoom_level = mMap.getCameraPosition().zoom; Log.d("CAC", "zoom level:" + zoom_level); if (zoom_level > 15.5) { if (adapter == null) { adapter = new InfoWindowContentAdapter(); } adapter.setData(cluster); mMap.animateCamera( CameraUpdateFactory.newLatLng(cluster.getPosition()), 200, new GoogleMap.CancelableCallback() { @Override public void onFinish() { AlertDialog dialog = new AlertDialog.Builder(mContext) .setAdapter( adapter, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d("CAC", "which:" + which); Case _case = adapter.getItem(which); } }) .create(); dialog.show(); } @Override public void onCancel() {} }); return true; } return false; }
@Override protected void onBeforeClusterRendered(Cluster<Case> cluster, MarkerOptions markerOptions) { ArrayList<Case> case_array = new ArrayList<Case>(cluster.getItems()); float avg = getAverageUnitPrice(case_array); int drawable_id = R.drawable.yellow_cluster_marker; if (avg <= average_unit_price_90p) { drawable_id = R.drawable.blue_cluster_marker; } else if (avg >= average_unit_price_110p) { drawable_id = R.drawable.red_cluster_marker; } DecimalFormat df = new DecimalFormat("0.0"); float compare_value = Float.parseFloat(df.format(avg)); if (Float.compare(avg, compare_value) > 0) { avg = Float.parseFloat(df.format(compare_value + 0.1f)); } else { avg = compare_value; } Bitmap icon = generateMarkerIcon(drawable_id, String.valueOf(avg) + "萬/坪"); markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)); }
@Override public Case getItem(int position) { return (Case) _cluster.getItems().toArray()[position]; }
@Override public int getCount() { return _cluster.getSize(); }
@Override protected boolean shouldRenderAsCluster(Cluster cluster) { // Always render clusters. return cluster.getSize() > 1; }
@Override protected boolean shouldRenderAsCluster(Cluster<MarkerData> cluster) { return cluster.getSize() > 1; }
/** Determine whether the cluster should be rendered as individual markers or a cluster. */ protected boolean shouldRenderAsCluster(Cluster<T> cluster) { return cluster.getSize() > MIN_CLUSTER_SIZE; }
@SuppressLint("NewApi") public void run() { if (clusters.equals(DefaultClusterRenderer.this.mClusters)) { mCallback.run(); return; } final MarkerModifier markerModifier = new MarkerModifier(); final float zoom = mMapZoom; final boolean zoomingIn = zoom > mZoom; final float zoomDelta = zoom - mZoom; final Set<MarkerWithPosition> markersToRemove = mMarkers; final LatLngBounds visibleBounds = mProjection.getVisibleRegion().latLngBounds; // TODO: Add some padding, so that markers can animate in from off-screen. // Find all of the existing clusters that are on-screen. These are candidates for // markers to animate from. List<Point> existingClustersOnScreen = null; if (DefaultClusterRenderer.this.mClusters != null && SHOULD_ANIMATE) { existingClustersOnScreen = new ArrayList<Point>(); for (Cluster<T> c : DefaultClusterRenderer.this.mClusters) { if (shouldRenderAsCluster(c) && visibleBounds.contains(c.getPosition())) { Point point = mSphericalMercatorProjection.toPoint(c.getPosition()); existingClustersOnScreen.add(point); } } } // Create the new markers and animate them to their new positions. final Set<MarkerWithPosition> newMarkers = new HashSet<MarkerWithPosition>(); for (Cluster<T> c : clusters) { boolean onScreen = visibleBounds.contains(c.getPosition()); if (zoomingIn && onScreen && SHOULD_ANIMATE) { Point point = mSphericalMercatorProjection.toPoint(c.getPosition()); Point closest = findClosestCluster(existingClustersOnScreen, point); if (closest != null) { LatLng animateTo = mSphericalMercatorProjection.toLatLng(closest); markerModifier.add(true, new CreateMarkerTask(c, newMarkers, animateTo)); } else { markerModifier.add(true, new CreateMarkerTask(c, newMarkers, null)); } } else { markerModifier.add(onScreen, new CreateMarkerTask(c, newMarkers, null)); } } // Wait for all markers to be added. markerModifier.waitUntilFree(); // Don't remove any markers that were just added. This is basically anything that had // a hit in the MarkerCache. markersToRemove.removeAll(newMarkers); // Find all of the new clusters that were added on-screen. These are candidates for // markers to animate from. List<Point> newClustersOnScreen = null; if (SHOULD_ANIMATE) { newClustersOnScreen = new ArrayList<Point>(); for (Cluster<T> c : clusters) { if (shouldRenderAsCluster(c) && visibleBounds.contains(c.getPosition())) { Point p = mSphericalMercatorProjection.toPoint(c.getPosition()); newClustersOnScreen.add(p); } } } // Remove the old markers, animating them into clusters if zooming out. for (final MarkerWithPosition marker : markersToRemove) { boolean onScreen = visibleBounds.contains(marker.position); // Don't animate when zooming out more than 3 zoom levels. // TODO: drop animation based on speed of device & number of markers to animate. if (!zoomingIn && zoomDelta > -3 && onScreen && SHOULD_ANIMATE) { final Point point = mSphericalMercatorProjection.toPoint(marker.position); final Point closest = findClosestCluster(newClustersOnScreen, point); if (closest != null) { LatLng animateTo = mSphericalMercatorProjection.toLatLng(closest); markerModifier.animateThenRemove(marker, marker.position, animateTo); } else { markerModifier.remove(true, marker.marker); } } else { markerModifier.remove(onScreen, marker.marker); } } markerModifier.waitUntilFree(); mMarkers = newMarkers; DefaultClusterRenderer.this.mClusters = clusters; mZoom = zoom; mCallback.run(); }