All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mapbox.mapboxsdk.annotations.MarkerViewManager Maven / Gradle / Ivy

There is a newer version: 9.2.1
Show newest version
package com.mapbox.mapboxsdk.annotations;

import android.content.Context;
import android.graphics.PointF;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.util.Pools;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.Projection;
import com.mapbox.mapboxsdk.utils.AnimatorUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Interface for interacting with ViewMarkers objects inside of a MapView.
 * 

* This class is responsible for managing a {@link MarkerView} item. *

*/ public class MarkerViewManager { private Map markerViewMap; private MapboxMap mapboxMap; private MapView mapView; private List markerViewAdapters; private long viewMarkerBoundsUpdateTime; private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener; private ImageMarkerViewAdapter defaultMarkerViewAdapter; /** * Creates an instance of MarkerViewManager. * * @param mapboxMap the MapboxMap associated with the MarkerViewManager * @param mapView the MapView associated with the MarkerViewManager */ public MarkerViewManager(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) { this.mapboxMap = mapboxMap; this.markerViewAdapters = new ArrayList<>(); this.mapView = mapView; this.markerViewMap = new HashMap<>(); this.defaultMarkerViewAdapter = new ImageMarkerViewAdapter(mapView.getContext()); this.markerViewAdapters.add(defaultMarkerViewAdapter); } /** * Animate a MarkerView to a given rotation. *

* The {@link MarkerView} will be rotated from its current rotation to the given rotation. *

* * @param marker the MarkerView to rotate * @param rotation the rotation value */ public void animateRotation(@NonNull MarkerView marker, float rotation) { View convertView = markerViewMap.get(marker); if (convertView != null) { AnimatorUtils.rotate(convertView, rotation); } } /** * Animate a MarkerView to a given alpha value. *

* The {@link MarkerView} will be transformed from its current alpha value to the given value. *

* * @param marker the MarkerView to change its alpha value * @param alpha the alpha value */ public void animateAlpha(@NonNull MarkerView marker, float alpha) { View convertView = markerViewMap.get(marker); if (convertView != null) { AnimatorUtils.alpha(convertView, alpha); } } /** * Animate a MarkerVIew to be visible or invisible *

* The {@link MarkerView} will be made {@link View#VISIBLE} or {@link View#GONE}. *

* * @param marker the MarkerView to change its visibility * @param visible the flag indicating if MarkerView is visible */ public void animateVisible(@NonNull MarkerView marker, boolean visible) { View convertView = markerViewMap.get(marker); if (convertView != null) { convertView.setVisibility(visible ? View.VISIBLE : View.GONE); } } /** * Updates the position of MarkerViews currently found in the viewport. *

* The collection of {@link MarkerView} will be iterated and each item position will be updated. * If an item is View state is not visible and its related flag is set to visible, * The {@link MarkerView} will be animated to visible using alpha animation. *

*/ public void update() { View convertView; for (MarkerView marker : markerViewMap.keySet()) { convertView = markerViewMap.get(marker); if (convertView != null) { PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition()); int x = (int) (marker.getAnchorU() * convertView.getMeasuredWidth()); int y = (int) (marker.getAnchorV() * convertView.getMeasuredHeight()); marker.setOffsetX(x); marker.setOffsetY(y); convertView.setX(point.x - x); convertView.setY(point.y - y); if (marker.isVisible() && convertView.getVisibility() == View.GONE) { convertView.animate().cancel(); convertView.setAlpha(0); AnimatorUtils.alpha(convertView, 1); } } } } /** * Set tilt on every non flat MarkerView currently shown in the Viewport. * * @param tilt the tilt value */ public void setTilt(float tilt) { View convertView; for (MarkerView markerView : markerViewMap.keySet()) { if (markerView.isFlat()) { convertView = markerViewMap.get(markerView); if (convertView != null) { markerView.setTilt(tilt); convertView.setRotationX(tilt); } } } } /** * */ public void updateIcon(@NonNull MarkerView markerView) { View convertView = markerViewMap.get(markerView); if (convertView != null && convertView instanceof ImageView) { ((ImageView) convertView).setImageBitmap(markerView.getIcon().getBitmap()); } } /** * Animate a MarkerView to a deselected state. *

* The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onDeselect(MarkerView, View)} will be called to execute an animation. *

* * @param marker the MarkerView to deselect */ public void deselect(@NonNull MarkerView marker) { final View convertView = markerViewMap.get(marker); if (convertView != null) { for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { if (adapter.getMarkerClass().equals(marker.getClass())) { adapter.onDeselect(marker, convertView); } } } } /** * Animate a MarkerView to a selected state. * * @param marker the MarkerView object to select */ public void select(@NonNull MarkerView marker) { final View convertView = markerViewMap.get(marker); for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { if (adapter.getMarkerClass().equals(marker.getClass())) { select(marker, convertView, adapter); } } } /** * Animate a MarkerView to a selected state. *

* The {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter#onSelect(MarkerView, View, boolean)} will be called to execute an animation. *

* @param marker the MarkerView object to select * @param convertView the View presentation of the MarkerView * @param adapter the adapter used to adapt the marker to the convertView */ public void select(@NonNull MarkerView marker, View convertView, MapboxMap.MarkerViewAdapter adapter) { if (convertView != null) { if (adapter.onSelect(marker, convertView, false)) { mapboxMap.selectMarker(marker); } marker.setSelected(true); } } /** * Get view representation from a MarkerView. *

* If marker is not found in current viewport, null is returned. *

* * @param marker the marker to get the view for * @return the android SDK View object */ @Nullable public View getView(MarkerView marker) { return markerViewMap.get(marker); } /** * Remove a MarkerView from a map. *

* The {@link MarkerView} will be removed using an alpha animation and related {@link View} * will be released to the android.support.v4.util.Pools.SimplePool from the related * {@link com.mapbox.mapboxsdk.maps.MapboxMap.MarkerViewAdapter}. It's possible to remove * the {@link MarkerView} from the underlying collection if needed. *

* * @param marker the MarkerView to remove */ public void removeMarkerView(MarkerView marker) { final View viewHolder = markerViewMap.get(marker); if (viewHolder != null && marker != null) { for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { if (adapter.getMarkerClass().equals(marker.getClass())) { if (adapter.prepareViewForReuse(marker, viewHolder)) { adapter.releaseView(viewHolder); } } } } markerViewMap.remove(marker); } /** * Add a MarkerViewAdapter to the MarkerViewManager. *

* The provided MarkerViewAdapter must use supply a generic subclass of MarkerView. *

* * @param markerViewAdapter the MarkerViewAdapter to add */ public void addMarkerViewAdapter(MapboxMap.MarkerViewAdapter markerViewAdapter) { if (markerViewAdapter.getMarkerClass().equals(MarkerView.class)) { throw new RuntimeException("Providing a custom MarkerViewAdapter requires subclassing MarkerView"); } if (!markerViewAdapters.contains(markerViewAdapter)) { markerViewAdapters.add(markerViewAdapter); invalidateViewMarkersInBounds(); } } /** * Get all MarkerViewAdapters associated with this MarkerViewManager. * * @return a List of MarkerViewAdapters */ public List getMarkerViewAdapters() { return markerViewAdapters; } /** * Register a callback to be invoked when this view is clicked. * * @param listener the callback to be invoked */ public void setOnMarkerViewClickListener(@Nullable MapboxMap.OnMarkerViewClickListener listener) { onMarkerViewClickListener = listener; } /** * Schedule that ViewMarkers found in the viewport are invalidated. *

* This method is rate limited, and {@link #invalidateViewMarkersInBounds} will only be called * once each 250 ms. *

*/ public void scheduleViewMarkerInvalidation() { if (!markerViewAdapters.isEmpty()) { long currentTime = SystemClock.elapsedRealtime(); if (currentTime < viewMarkerBoundsUpdateTime) { return; } invalidateViewMarkersInBounds(); viewMarkerBoundsUpdateTime = currentTime + 250; } } /** * Invalidate the ViewMarkers found in the viewport. *

* This method will remove any markers that aren't in the viewport any more and will add new * ones for each found Marker in the changed viewport. *

*/ public void invalidateViewMarkersInBounds() { Projection projection = mapboxMap.getProjection(); List markers = mapView.getMarkerViewsInBounds(projection.getVisibleRegion().latLngBounds); View convertView; // remove old markers Iterator iterator = markerViewMap.keySet().iterator(); while (iterator.hasNext()) { MarkerView m = iterator.next(); if (!markers.contains(m)) { // remove marker convertView = markerViewMap.get(m); for (MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { if (adapter.getMarkerClass().equals(m.getClass())) { adapter.prepareViewForReuse(m, convertView); adapter.releaseView(convertView); iterator.remove(); } } } } // introduce new markers for (final MarkerView marker : markers) { if (!markerViewMap.containsKey(marker)) { for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) { if (adapter.getMarkerClass().equals(marker.getClass())) { convertView = (View) adapter.getViewReusePool().acquire(); final View adaptedView = adapter.getView(marker, convertView, mapView); if (adaptedView != null) { // tilt adaptedView.setRotationX(marker.getTilt()); // rotation adaptedView.setRotation(marker.getRotation()); // alpha adaptedView.setAlpha(marker.getAlpha()); // visible adaptedView.setVisibility(marker.isVisible() ? View.VISIBLE : View.GONE); if (mapboxMap.getSelectedMarkers().contains(marker)) { // if a marker to be shown was selected // replay that animation with duration 0 if (adapter.onSelect(marker, adaptedView, true)) { mapboxMap.selectMarker(marker); } } adaptedView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(final View v) { boolean clickHandled = false; if (onMarkerViewClickListener != null) { clickHandled = onMarkerViewClickListener.onMarkerClick(marker, v, adapter); } if (!clickHandled) { // InfoWindow offset int infoWindowOffsetX = (int) ((adaptedView.getWidth() * marker.getInfoWindowAnchorU()) - marker.getOffsetX()); int infoWindowOffsetY = (int) ((adaptedView.getHeight() * marker.getInfoWindowAnchorV()) - marker.getOffsetY()); marker.setTopOffsetPixels(infoWindowOffsetY); marker.setRightOffsetPixels(infoWindowOffsetX); select(marker, v, adapter); } } }); markerViewMap.put(marker, adaptedView); if (convertView == null) { mapView.addView(adaptedView); } } } } } } } /** * Default MarkerViewAdapter used for base class of MarkerView to adapt a MarkerView to an ImageView */ public static class ImageMarkerViewAdapter extends MapboxMap.MarkerViewAdapter { private LayoutInflater inflater; public ImageMarkerViewAdapter(Context context) { super(context); inflater = LayoutInflater.from(context); } @Nullable @Override public View getView(@NonNull MarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); convertView = inflater.inflate(R.layout.view_image_marker, parent, false); viewHolder.imageView = (ImageView) convertView.findViewById(R.id.image); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.imageView.setImageBitmap(marker.getIcon().getBitmap()); return convertView; } private static class ViewHolder { ImageView imageView; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy