[android] - cleanup marker view integration

This commit is contained in:
Tobrun
2016-05-23 12:02:51 +02:00
parent 40bb02fe74
commit 98f8dd6ae6
7 changed files with 179 additions and 188 deletions

View File

@@ -22,7 +22,7 @@ public abstract class Annotation implements Comparable<Annotation> {
* Internal C++ id is stored as unsigned int.
*/
private long id = -1; // -1 unless added to a MapView
private MapboxMap mapboxMap;
protected MapboxMap mapboxMap;
protected Annotation() {
}

View File

@@ -7,6 +7,8 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
public class MarkerView extends Marker {
private MarkerViewManager markerViewManager;
private PointF centerOffset;
private Point infoWindowOffset;
private boolean flat;
@@ -16,9 +18,7 @@ public class MarkerView extends Marker {
private float tiltValue;
private float rotation;
private float alpha;
private MarkerViewTransformer markerViewTransformer;
private float alpha = 1;
MarkerView() {
centerOffset = new PointF();
@@ -74,18 +74,18 @@ public class MarkerView extends Marker {
this.deselectAnimRes = deselectAnimRes;
}
public float getTiltValue() {
float getTilt() {
return tiltValue;
}
public void setTiltValue(float tiltValue) {
void setTilt(float tiltValue) {
this.tiltValue = tiltValue;
}
public void setRotation(float rotation) {
this.rotation = rotation;
if (markerViewTransformer != null) {
markerViewTransformer.animateRotation(this, rotation);
if (markerViewManager != null) {
markerViewManager.animateRotation(this, rotation);
}
}
@@ -99,15 +99,14 @@ public class MarkerView extends Marker {
public void setAlpha(float alpha) {
this.alpha = alpha;
if (markerViewTransformer != null) {
markerViewTransformer.animateAlpha(this, rotation);
if (markerViewManager != null) {
markerViewManager.animateAlpha(this, alpha);
}
}
@Override
public void setMapboxMap(MapboxMap mapboxMap) {
super.setMapboxMap(mapboxMap);
MarkerViewManager manager = mapboxMap.getMarkerViewManager();
markerViewTransformer = manager.getMarkerViewTransformer();
markerViewManager = mapboxMap.getMarkerViewManager();
}
}

View File

@@ -1,69 +1,96 @@
package com.mapbox.mapboxsdk.annotations;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
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.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.View;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
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;
public class MarkerViewManager {
private Map<MarkerView, View> mMarkerViewMap;
private MapboxMap mapboxMap;
private MapView mapView;
private Context context;
private List<MapboxMap.MarkerViewAdapter> markerViewAdapters;
private MarkerViewTransformer markerViewTransformer;
private long mViewMarkerBoundsUpdateTime;
private MapboxMap.OnMarkerViewClickListener onMarkerViewClickListener;
private Bitmap mViewMarkerBitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
public MarkerViewManager(@NonNull MapboxMap mapboxMap, @NonNull MapView mapView) {
this.mapboxMap = mapboxMap;
this.markerViewAdapters = new ArrayList<>();
this.markerViewTransformer = new MarkerViewTransformer();
this.mapView = mapView;
this.context = mapView.getContext().getApplicationContext();
mMarkerViewMap = new HashMap<>();
}
public void animateRotation(@NonNull MarkerView marker, float rotation) {
View convertView = mMarkerViewMap.get(marker);
if (convertView != null) {
AnimatorUtils.rotate(convertView, rotation);
}
}
public void animateAlpha(@NonNull MarkerView marker, float alpha) {
View convertView = mMarkerViewMap.get(marker);
if (convertView != null) {
AnimatorUtils.alpha(convertView, alpha);
}
}
public void update() {
View convertView;
for (MarkerView marker : mMarkerViewMap.keySet()) {
convertView = mMarkerViewMap.get(marker);
if (convertView != null) {
PointF point = mapboxMap.getProjection().toScreenLocation(marker.getPosition());
convertView.setX(point.x - (convertView.getMeasuredWidth() / 2));
convertView.setY(point.y - (convertView.getMeasuredHeight() / 2));
if (convertView.getVisibility() == View.GONE) {
convertView.animate().cancel();
convertView.setAlpha(0);
AnimatorUtils.alpha(convertView, 1);
}
}
}
}
public void setTilt(float tilt) {
View convertView;
for (MarkerView markerView : mMarkerViewMap.keySet()) {
if (markerView.isFlat()) {
convertView = mMarkerViewMap.get(markerView);
if (convertView != null) {
markerView.setTilt(tilt);
convertView.setRotationX(tilt);
}
}
}
}
public void deselect(@NonNull MarkerView marker) {
final View viewMarker = markerViewTransformer.getMarkerViewMap().get(marker);
if (viewMarker != null) {
final View convertView = mMarkerViewMap.get(marker);
if (convertView != null) {
int deselectAnimatorRes = marker.getDeselectAnimRes();
if (deselectAnimatorRes != 0) {
viewMarker.setLayerType(View.LAYER_TYPE_HARDWARE, null);
Animator animator = AnimatorInflater.loadAnimator(context, deselectAnimatorRes);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
viewMarker.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
animator.setTarget(viewMarker);
animator.start();
AnimatorUtils.animate(convertView, deselectAnimatorRes);
}
}
}
public void removeMarkerView(MarkerView marker, boolean removeFromMap) {
final View viewHolder = markerViewTransformer.getMarkerViewMap().get(marker);
final View viewHolder = mMarkerViewMap.get(marker);
if (viewHolder != null && marker != null) {
for (final MapboxMap.MarkerViewAdapter<?> adapter : markerViewAdapters) {
if (adapter.getMarkerClass() == marker.getClass()) {
@@ -74,33 +101,21 @@ public class MarkerViewManager {
// cancel ongoing animations
viewHolder.animate().cancel();
viewHolder.setAlpha(1);
// animate alpha
viewHolder.animate()
.alpha(0)
.setDuration(MapboxConstants.ANIMATION_DURATION_SHORT)
.setInterpolator(new FastOutSlowInInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
viewHolder.setVisibility(View.GONE);
viewPool.release(viewHolder);
}
});
AnimatorUtils.alpha(viewHolder, 0, new AnimatorUtils.OnAnimationEndListener() {
@Override
public void onAnimationEnd() {
viewHolder.setVisibility(View.GONE);
viewPool.release(viewHolder);
}
});
}
}
}
if (removeFromMap) {
markerViewTransformer.getMarkerViewMap().remove(marker);
mMarkerViewMap.remove(marker);
}
}
public MarkerViewTransformer getMarkerViewTransformer() {
return markerViewTransformer;
}
public void addMarkerViewAdapter(@Nullable MapboxMap.MarkerViewAdapter markerViewAdapter) {
if (!markerViewAdapters.contains(markerViewAdapter)) {
markerViewAdapters.add(markerViewAdapter);
@@ -130,22 +145,18 @@ public class MarkerViewManager {
public void invalidateViewMarkersInBounds() {
Projection projection = mapboxMap.getProjection();
List<MarkerView> markers = mapView.getMarkerViewsInBounds(projection.getVisibleRegion().latLngBounds);
Map<MarkerView, View> markerView = markerViewTransformer.getMarkerViewMap();
View convertView;
// remove old markers
Iterator<MarkerView> iterator = markerView.keySet().iterator();
Iterator<MarkerView> iterator = mMarkerViewMap.keySet().iterator();
while (iterator.hasNext()) {
MarkerView m = iterator.next();
if (!markers.contains(m)) {
// remove marker
convertView = markerView.get(m);
convertView = mMarkerViewMap.get(m);
int deselectAnimRes = m.getDeselectAnimRes();
if (deselectAnimRes != 0) {
Animator animator = AnimatorInflater.loadAnimator(context, deselectAnimRes);
animator.setDuration(0);
animator.setTarget(convertView);
animator.start();
AnimatorUtils.animate(convertView, deselectAnimRes, 0);
}
removeMarkerView(m, false);
iterator.remove();
@@ -154,7 +165,7 @@ public class MarkerViewManager {
// introduce new markers
for (final MarkerView marker : markers) {
if (!markerView.containsKey(marker)) {
if (!mMarkerViewMap.containsKey(marker)) {
for (final MapboxMap.MarkerViewAdapter adapter : markerViewAdapters) {
if (adapter.getMarkerClass() == marker.getClass()) {
convertView = (View) adapter.getViewReusePool().acquire();
@@ -168,20 +179,20 @@ public class MarkerViewManager {
if (adaptedView != null) {
// tilt
adaptedView.setRotationX(marker.getTiltValue());
adaptedView.setRotationX(marker.getTilt());
// rotation
adaptedView.setRotation(marker.getRotation());
// alpha
adaptedView.setAlpha(marker.getAlpha());
if (mapboxMap.getSelectedMarkers().contains(marker)) {
// if a marker to be shown was selected
// replay that animation with duration 0
int selectAnimRes = marker.getSelectAnimRes();
if (selectAnimRes != 0) {
Animator animator = AnimatorInflater.loadAnimator(mapView.getContext(), selectAnimRes);
animator.setDuration(0);
animator.setTarget(convertView);
animator.start();
AnimatorUtils.animate(convertView, selectAnimRes, 0);
}
}
@@ -196,18 +207,12 @@ public class MarkerViewManager {
if (!clickHandled) {
if (animSelectRes != 0) {
v.setLayerType(View.LAYER_TYPE_HARDWARE, null);
Animator animator = AnimatorInflater.loadAnimator(context, animSelectRes);
animator.setTarget(v);
animator.addListener(new AnimatorListenerAdapter() {
AnimatorUtils.animate(v, animSelectRes, new AnimatorUtils.OnAnimationEndListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
public void onAnimationEnd() {
mapboxMap.selectMarker(marker);
v.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
animator.start();
} else {
mapboxMap.selectMarker(marker);
}
@@ -215,7 +220,7 @@ public class MarkerViewManager {
}
});
markerView.put(marker, adaptedView);
mMarkerViewMap.put(marker, adaptedView);
if (convertView == null) {
mapView.addView(adaptedView);
}

View File

@@ -1,76 +0,0 @@
package com.mapbox.mapboxsdk.annotations;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.support.annotation.NonNull;
import android.view.View;
import java.util.HashMap;
import java.util.Map;
public class MarkerViewTransformer {
private Map<MarkerView, View> mMarkerViewMap;
public MarkerViewTransformer() {
mMarkerViewMap = new HashMap<>();
}
/**
* Animate the rotation of a marker view.
*
* @param markerView
* @param rotation
*/
public void animateRotation(@NonNull MarkerView markerView, float rotation) {
final View convertView = mMarkerViewMap.get(markerView);
if (convertView != null) {
convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, convertView.getRotation(), rotation);
rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
convertView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
rotateAnimator.start();
}
}
public void animateAlpha(@NonNull MarkerView markerView, float alpha) {
final View convertView = mMarkerViewMap.get(markerView);
if (convertView != null) {
convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha);
rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
convertView.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
rotateAnimator.start();
}
}
/**
* Set tilt to marker views in the viewport.
*
* @param tilt
*/
public void setTilt(float tilt) {
for (MarkerView markerView : mMarkerViewMap.keySet()) {
if (markerView.isFlat()) {
markerView.setTiltValue(tilt);
mMarkerViewMap.get(markerView).setRotationX(tilt);
}
}
}
public Map<MarkerView, View> getMarkerViewMap() {
return mMarkerViewMap;
}
}

View File

@@ -1,8 +1,6 @@
package com.mapbox.mapboxsdk.maps;
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
@@ -35,7 +33,6 @@ import android.support.annotation.UiThread;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ScaleGestureDetectorCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.AttributeSet;
@@ -98,7 +95,6 @@ import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -1362,33 +1358,7 @@ public class MapView extends FrameLayout {
mCompassView.update(getDirection());
mMyLocationView.update();
Map<MarkerView, View> viewMarkers = mMapboxMap.getMarkerViewManager().getMarkerViewTransformer().getMarkerViewMap();
for (Marker marker : viewMarkers.keySet()) {
mViewHolder = viewMarkers.get(marker);
if (mViewHolder != null) {
PointF point = mMapboxMap.getProjection().toScreenLocation(marker.getPosition());
mViewHolder.setX(point.x - (mViewHolder.getMeasuredWidth() / 2));
mViewHolder.setY(point.y - (mViewHolder.getMeasuredHeight() / 2));
if (mViewHolder.getVisibility() == GONE) {
mViewHolder.animate().cancel();
mViewHolder.setAlpha(0);
mViewHolder.animate()
.alpha(1)
.setDuration(MapboxConstants.ANIMATION_DURATION_SHORT)
.setInterpolator(new FastOutSlowInInterpolator())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
mViewHolder.setVisibility(VISIBLE);
}
})
.start();
}
}
}
mMapboxMap.getMarkerViewManager().update();
for (InfoWindow infoWindow : mMapboxMap.getInfoWindows()) {
infoWindow.update();

View File

@@ -637,7 +637,7 @@ public class MapboxMap {
//
void setTilt(double tilt) {
mMarkerViewManager.getMarkerViewTransformer().setTilt((float) tilt);
mMarkerViewManager.setTilt((float) tilt);
mMapView.setTilt(tilt);
}

View File

@@ -0,0 +1,93 @@
package com.mapbox.mapboxsdk.utils;
import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.support.annotation.AnimatorRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
public class AnimatorUtils {
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, @Nullable OnAnimationEndListener listener) {
animate(view, animatorRes, -1, listener);
}
public static void animate(final View view, @AnimatorRes int animatorRes, int duration, @Nullable final OnAnimationEndListener listener) {
if (view == null) {
return;
}
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
Animator animator = AnimatorInflater.loadAnimator(view.getContext(), animatorRes);
if (duration != -1) {
animator.setDuration(duration);
}
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setLayerType(View.LAYER_TYPE_NONE, null);
if (listener != null) {
listener.onAnimationEnd();
}
}
});
animator.setTarget(view);
animator.start();
}
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes) {
animate(view, animatorRes, -1);
}
public static void animate(@NonNull final View view, @AnimatorRes int animatorRes, int duration) {
animate(view, animatorRes, duration, null);
}
public static void rotate(@NonNull final View view, float rotation) {
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(view, View.ROTATION, view.getRotation(), rotation);
rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
view.setLayerType(View.LAYER_TYPE_NONE, null);
}
});
rotateAnimator.start();
}
public static void alpha(@NonNull final View convertView, float alpha, @Nullable final OnAnimationEndListener listener) {
convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ALPHA, convertView.getAlpha(), alpha);
rotateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
convertView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
convertView.setLayerType(View.LAYER_TYPE_NONE, null);
if (listener != null) {
listener.onAnimationEnd();
}
}
});
rotateAnimator.start();
}
public static void alpha(@NonNull final View convertView, float alpha) {
alpha(convertView, alpha, null);
}
public interface OnAnimationEndListener {
void onAnimationEnd();
}
}