2016-02-26 3 views
8

Я хочу изменить фон маркера кластера при щелчке. Я делаю это с помощьюDefaultClusterRenderer getMarker() возвращает значение null при масштабировании

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

Это прекрасно работает ожидать в одном случае: Когда я увеличивать или уменьшать масштаб и количество кластера маркеров не меняется. Например, если у меня было кластер из 15 кластеров и 5, а затем увеличьте уровень в или из, те же два кластера остаются. Нажав на один из них, теперь renderer.getMarker(cluster) возвращает null. Если они повторно кластеризуются после масштабирования, getMarker не равен нулю.

My DefaultClusterRenderer находится ниже. Я проверил маркер на onClusteredRendered, и он никогда не был нулевым. Является ли это ошибкой в ​​DefaultClusterRenderer или мне нужно сделать что-то еще?

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

Инициализация 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: Эта инициализация работает для меня:

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

Я не могу воспроизвести ваше поведение с помощью демонстрационного приложения. Как вы добавляете свои элементы в кластер? Я бы поспорил, что это скорее проблема жизненного цикла, а не проблема с вашим Renderer. Я также сказал бы, что вы получаете нулевой маркер при вызове 'renderer.getMarker (cluster);' потому что кластер, который вы получаете на 'onClusterClick (кластер кластер)', является нулевым. – antonio

+0

кластер никогда не имеет значения null. i обновил код выше при инициализации 'ClusterManager' – ono

+0

Хорошо, позвольте мне проверить поведение моего примера с кодом инициализации. – antonio

ответ

3

Не удалось получить renderer.getMarker(cluster) вернуть маркер в этом случае выше. Произведение вокруг было создать:

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

затем добавить их на DefaultClusterRenderer обратного вызова, потому что маркер никогда не нуль есть:

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

Поскольку DefaultClusterManager очищает их при изменении положения камеры, протирать кластер маркер карты перед ним создает новые:

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

Теперь я могу получить маркер успешно clusterMarkerMap.get(cluster)

Смежные вопросы