2016-02-26 7 views
8

Ich möchte den Hintergrund des Cluster-Markers bei Klick ändern. Ich tue dies überDefaultClusterRenderer getMarker() gibt Null beim Zoomen zurück

@Override 
onClusterClick(Cluster<MyObject> cluster) { 
    Marker marker = renderer.getMarker(cluster); 
    marker.setIcon(....); 
} 

Dies funktioniert gut für einen Fall erwarten: Wenn wir vergrößern oder verkleinern und die Anzahl der Cluster-Markierungen ändert sich nicht. Wenn ich zum Beispiel einen Cluster von 15 und einen Cluster von 5 hätte, dann zoome einen Level hinein oder heraus, bleiben die gleichen zwei Cluster übrig. Klicken Sie auf eine dieser jetzt renderer.getMarker(cluster) gibt null zurück. Wenn sie nach dem Zoomen neu gruppieren, ist getMarker nicht null.

Mein DefaultClusterRenderer ist unten. Ich habe den Marker auf onClusteredRendered überprüft und es ist nie null. Ist das ein Fehler im DefaultClusterRenderer oder sollte ich etwas anderes machen?

private class MyRenderer extends DefaultClusterRenderer<MyObject> { 

    private IconGenerator iconGenerator; 
    private float density; 

    public MyRenderer(Context context, GoogleMap map, ClusterManager<MyObject> clusterManager) { 
     super(context, map, clusterManager); 
     density = context.getResources().getDisplayMetrics().density; 
    } 

    @Override 
    protected void onBeforeClusterItemRendered(MyObject item, MarkerOptions markerOptions) { 
     markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.my_pin)); 
    } 

    @Override 
    protected void onBeforeClusterRendered(Cluster<MyObject> cluster, MarkerOptions markerOptions) { 
     if(iconGenerator == null) { 
      iconGenerator = new IconGenerator(getActivity()); 
      iconGenerator.setContentView(makeTextView(getActivity())); 
     } 
     iconGenerator.setBackground(makeBackground(false)); 

     markerOptions.icon(BitmapDescriptorFactory.fromBitmap(iconGenerator.makeIcon(String.valueOf(cluster.getSize())))); 
    } 

    @Override 
    protected void onClusterRendered(Cluster<MyObject> cluster, Marker marker) { 
     super.onClusterRendered(cluster, marker); 
     // Marker is never null here 

    } 

    @Override 
    protected boolean shouldRenderAsCluster(Cluster<MyObject> cluster) { 
     return cluster.getSize() > 1; 
    } 

    private ShapeDrawable makeBackground(boolean isClicked) { 
     ShapeDrawable background = new ShapeDrawable(new OvalShape()); 
     background.setColorFilter(ContextCompat.getColor(getActivity(), 
       isClicked ? R.color.cluster_marker_clicked : R.color.cluster_marker_unclicked), PorterDuff.Mode.SRC_ATOP); 

     return background; 
    } 

    private SquareTextView makeTextView(Context context) { 
     SquareTextView squareTextView = new SquareTextView(context); 

     ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(-2, -2); 
     squareTextView.setLayoutParams(layoutParams); 
     squareTextView.setTextColor(ContextCompat.getColor(getActivity(), R.color.white)); 

     squareTextView.setTypeface(Utils.getFontBold(getActivity())); 

     squareTextView.setId(com.google.maps.android.R.id.text); 
     int twelveDpi = (int) (12.0F * density); 
     squareTextView.setPadding(twelveDpi, twelveDpi, twelveDpi, twelveDpi); 

     return squareTextView; 
    } 

    public IconGenerator getIconGenerator(boolean isClicked) { 
     iconGenerator.setBackground(makeBackground(isClicked)); 
     return iconGenerator; 
    } 
} 

initialisieren ClusterManager:

final ClusterManager<MyObject> mClusterManager = new ClusterManager<>(getActivity(), googleMap); 
    mClusterManager.addItems(items); 

    renderer = new CustomRenderer(getActivity(), googleMap, mClusterManager); 
    mClusterManager.setRenderer(renderer); 
    mClusterManager.cluster(); 

    mClusterManager.setOnClusterItemClickListener(this); 

    googleMap.setOnMarkerClickListener(mClusterManager); 

@antonio: Diese Initialisierung für mich funktioniert:

public class MapsActivity extends FragmentActivity 
     implements ClusterManager.OnClusterClickListener<MyObject> { 

    // ... 

    private void setUpClusterer() { 
     googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); 

     mClusterManager = new ClusterManager<MyObject>(this, googleMap); 
     mClusterManager.setOnClusterClickListener(this); 
     renderer = new MyRenderer(this, googleMap, mClusterManager); 
     mClusterManager.setRenderer(renderer); 

     googleMap.setOnCameraChangeListener(mClusterManager); 
     googleMap.setOnMarkerClickListener(mClusterManager); 

     addItems(); 
    } 

    private void addItems() { 
     // Set some lat/lng coordinates to start with. 
     double lat = 51.5145160; 
     double lng = -0.1270060; 

     // Add ten cluster items in close proximity, for purposes of this example. 
     for (int i = 0; i < 10; i++) { 
      double offset = i/60d; 
      lat = lat + offset; 
      lng = lng + offset; 
      MyObject offsetItem = new MyObject(lat, lng); 
      mClusterManager.addItem(offsetItem); 
     } 
    } 

    @Override 
    public boolean onClusterClick(final Cluster<MyObject> cluster) { 
     Marker marker = renderer.getMarker(cluster); 
     marker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.my_newpin)); 

     return true; 
    } 
} 
+0

Ich kann Ihr Verhalten nicht mit der Demo-App reproduzieren. Wie fügen Sie Ihre Artikel zum Cluster hinzu? Ich würde wetten, dass dies eher ein Lebenszyklusproblem als ein Problem mit Ihrem Renderer ist. Ich würde auch sagen, dass Sie einen null 'Marker' beim Aufrufen von 'renderer.getMarker (cluster);' erhalten, weil der Cluster, den Sie auf 'onClusterClick (Cluster cluster) erhalten 'null ist. – antonio

+0

Cluster ist nie null. Ich habe den obigen Code aktualisiert, als ich den 'ClusterManager' initiierte. – ono

+0

Ok, lass mich das Verhalten meines Beispiels mit deinem Initialisierungscode testen – antonio

Antwort

3

nicht renderer.getMarker(cluster) bekommen konnte über einen Marker in diesem Fall zurückzukehren. Eine Arbeit war um zu erstellen:

Map <Cluster<MyObject>, Marker> clusterMarkerMap = new HashMap<>(); 

sie dann auf dem DefaultClusterRenderer Rückruf hinzufügen, da der Marker nie null ist:

@Override 
protected void onClusterRendered(Cluster<MyObject> cluster, Marker marker) { 
    super.onClusterRendered(cluster, marker); 
    clusterMarkerMap.put(cluster, marker); 
} 

Da die DefaultClusterManager sie gelöscht, wenn die Kameraposition ändert, den Cluster wischen Markerkarte, bevor es schafft neue:

googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() { 
     @Override 
     public void onCameraChange(CameraPosition cameraPosition) { 
      // Clear the map here because the markers will be recreated 
      // when the manager is notified of a (zoom level) camera change 
      if(zoomLevelChanged) 
       clusterMarkerMap.clear(); 
      mClusterManager.onCameraChange(cameraPosition); 
     } 
    }); 

Jetzt kann ich den Marker erhalten erfolgreich clusterMarkerMap.get(cluster)