2016-02-26 22 views
8

Desidero modificare lo sfondo dell'indicatore del cluster al clic. Lo faccio attraversoDefaultClusterRenderer getMarker() restituisce null durante lo zoom

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

Questo funziona bene si aspettano per un caso: quando zoom avanti o indietro e il numero di indicatori di cluster non cambia. Ad esempio, se avessi un cluster a 15 e un cluster a 5, quindi ingrandisci o rimpicciolisci un livello, rimangono gli stessi due cluster. Cliccando su uno di questi ora renderer.getMarker(cluster) restituisce null. Se si ricombinano dopo lo zoom, getMarker non è nullo.

My DefaultClusterRenderer è qui sotto. Ho controllato il marker su onClusteredRendered e non è mai nullo. Si tratta di un bug in DefaultClusterRenderer o dovrei fare qualcos'altro?

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

inizializzazione del 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: Questa inizializzazione sta lavorando per me:

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

Non riesco a riprodurre il tuo comportamento con l'app demo. Come stai aggiungendo i tuoi articoli al cluster? Scommetto che questo è più un problema di ciclo di vita piuttosto che un problema con il tuo Renderer. Direi anche che stai ricevendo un 'Marker' nullo quando chiami' renderer.getMarker (cluster); 'perché il cluster che ricevi su' onClusterClick (Cluster cluster) 'è nullo. Il cluster – antonio

+0

non è mai nullo. ho aggiornato il codice qui sopra durante l'inizializzazione di 'ClusterManager' – ono

+0

Ok, permettimi di testare il comportamento del mio esempio con il tuo codice di inizializzazione – antonio

risposta

3

Impossibile ottenere renderer.getMarker(cluster) per restituire un marcatore in quel caso di cui sopra. Un lavoro in giro era quello di creare:

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

quindi aggiungerli sulla DefaultClusterRenderer richiamata perché il marcatore non è mai nullo c'è:

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

Perché il DefaultClusterManager li cancella quando la posizione cambia fotocamera, pulire il cluster mappa del marcatore prima di creare nuovi:

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

Ora posso ottenere il marcatore con successo clusterMarkerMap.get(cluster)