diff options
author | Tobrun Van Nuland <tobrun.van.nuland@gmail.com> | 2016-06-03 14:29:20 +0200 |
---|---|---|
committer | Tobrun <tobrun.van.nuland@gmail.com> | 2016-06-05 14:23:24 +0200 |
commit | 436c23c40b37c4863ddfbc25c6463ae2f2767a06 (patch) | |
tree | f5f78cd7d9deaaa8e16be10a8480e73f5f93b977 /platform/android/MapboxGLAndroidSDKTestApp | |
parent | 4094987fa09561c4c69b1b4cf8a6cbf9d3dd0433 (diff) | |
download | qtlocation-mapboxgl-436c23c40b37c4863ddfbc25c6463ae2f2767a06.tar.gz |
[android] #5171 - introduce new select/deselect animation system for view markers
Diffstat (limited to 'platform/android/MapboxGLAndroidSDKTestApp')
6 files changed, 287 insertions, 68 deletions
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java index 7a2241a84c..e4bf383c96 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/BulkMarkerActivity.java @@ -3,28 +3,28 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.app.ProgressDialog; -import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.annotation.Nullable; +import android.support.v4.content.res.ResourcesCompat; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; -import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; +import com.mapbox.mapboxsdk.annotations.Icon; +import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.annotations.Marker; import com.mapbox.mapboxsdk.annotations.MarkerOptions; -import com.mapbox.mapboxsdk.annotations.MarkerView; import com.mapbox.mapboxsdk.annotations.MarkerViewOptions; import com.mapbox.mapboxsdk.geometry.LatLng; import com.mapbox.mapboxsdk.maps.MapView; @@ -86,36 +86,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView } } - public static class TextAdapter extends MapboxMap.MarkerViewAdapter<MarkerView> { - - private LayoutInflater inflater; - - public TextAdapter(@NonNull Context context) { - super(context); - this.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_text_marker, parent, false); - viewHolder.title = (TextView) convertView.findViewById(R.id.textView); - convertView.setTag(viewHolder); - } else { - viewHolder = (ViewHolder) convertView.getTag(); - } - viewHolder.title.setText(marker.getTitle()); - return convertView; - } - - private static class ViewHolder { - TextView title; - } - } - @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { int amount = Integer.valueOf(getResources().getStringArray(R.array.bulk_marker_list)[position]); @@ -126,7 +96,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView } } - private void onLatLngListLoaded(List<LatLng> latLngs, int amount) { mLocations = latLngs; showMarkers(amount); @@ -140,26 +109,32 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView } if (mCustomMarkerView) { - showNativeMarkers(amount); + showViewMarkers(amount); } else { showGlMarkers(amount); } } - private void showNativeMarkers(int amount) { + private void showViewMarkers(int amount) { DecimalFormat formatter = new DecimalFormat("#.#####"); Random random = new Random(); int randomIndex; + Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_droppin_24dp, getTheme()); + int redColor = ResourcesCompat.getColor(getResources(), android.R.color.holo_red_dark, getTheme()); + drawable.setColorFilter(redColor, PorterDuff.Mode.SRC_IN); + Icon icon = IconFactory.getInstance(this).fromDrawable(drawable); + for (int i = 0; i < amount; i++) { randomIndex = random.nextInt(mLocations.size()); LatLng latLng = mLocations.get(randomIndex); mMapboxMap.addMarker(new MarkerViewOptions() .position(latLng) + .icon(icon) .title(String.valueOf(i)) .snippet(formatter.format(latLng.getLatitude()) + ", " + formatter.format(latLng.getLongitude()))); } - } + } private void showGlMarkers(int amount) { List<MarkerOptions> markerOptionsList = new ArrayList<>(); @@ -247,9 +222,6 @@ public class BulkMarkerActivity extends AppCompatActivity implements AdapterView showMarkers(amount); } - // add adapter - mMapboxMap.getMarkerViewManager().addMarkerViewAdapter(new TextAdapter(BulkMarkerActivity.this)); - mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { @Override public void onMapChanged(@MapView.MapChange int change) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java index 60ace581a4..93bed990fc 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/MarkerViewActivity.java @@ -1,5 +1,9 @@ package com.mapbox.mapboxsdk.testapp.activity.annotation; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; @@ -18,6 +22,8 @@ import android.widget.Toast; import com.mapbox.mapboxsdk.annotations.Icon; import com.mapbox.mapboxsdk.annotations.IconFactory; import com.mapbox.mapboxsdk.annotations.Marker; +import com.mapbox.mapboxsdk.annotations.MarkerOptions; +import com.mapbox.mapboxsdk.annotations.MarkerView; import com.mapbox.mapboxsdk.annotations.MarkerViewManager; import com.mapbox.mapboxsdk.annotations.MarkerViewOptions; import com.mapbox.mapboxsdk.geometry.LatLng; @@ -28,6 +34,8 @@ import com.mapbox.mapboxsdk.testapp.R; import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerOptions; import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerView; import com.mapbox.mapboxsdk.testapp.model.annotations.CountryMarkerViewOptions; +import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerView; +import com.mapbox.mapboxsdk.testapp.model.annotations.TextMarkerViewOptions; public class MarkerViewActivity extends AppCompatActivity { @@ -35,13 +43,10 @@ public class MarkerViewActivity extends AppCompatActivity { private MapView mMapView; private final static LatLng[] LAT_LNGS = new LatLng[]{ - new LatLng(38.907327, -77.041293), + new LatLng(38.897424, -77.036508), new LatLng(38.909698, -77.029642), new LatLng(38.907227, -77.036530), new LatLng(38.905607, -77.031916), - new LatLng(38.897424, -77.036508), - new LatLng(38.897642, -77.041980), - new LatLng(38.889876, -77.008849), new LatLng(38.889441, -77.050134) }; @@ -83,24 +88,40 @@ public class MarkerViewActivity extends AppCompatActivity { ); } - // add child classes of ViewMarker + // add custom ViewMarker CountryMarkerViewOptions options = new CountryMarkerViewOptions(); options.flagRes(R.drawable.icon_burned); options.abbrevName("Mapbox"); + options.title("Hello"); options.position(new LatLng(38.899774, -77.023237)); options.selectAnimatorResource(R.animator.rotate_360); options.deselectAnimatorResource(R.animator.rotate_360); options.flat(true); mapboxMap.addMarker(options); - // add default GL marker - mMapboxMap.addMarker(new CountryMarkerOptions() + mMapboxMap.addMarker(new MarkerOptions() .title("United States") .position(new LatLng(38.902580, -77.050102)) ); + mMapboxMap.addMarker(new TextMarkerViewOptions() + .text("A") + .position(new LatLng(38.889876, -77.008849)) + ); + + mMapboxMap.addMarker(new TextMarkerViewOptions() + .text("B") + .position(new LatLng(38.907327, -77.041293)) + ); + + mMapboxMap.addMarker(new TextMarkerViewOptions() + .text("C") + .position(new LatLng(38.897642, -77.041980)) + ); + // set adapters for child classes of ViewMarker - markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this)); + markerViewManager.addMarkerViewAdapter(new CountryAdapter(MarkerViewActivity.this, mapboxMap)); + markerViewManager.addMarkerViewAdapter(new TextAdapter(MarkerViewActivity.this, mapboxMap)); // add a change listener to validate the size of amount of child views mMapView.addOnMapChangedListener(new MapView.OnMapChangedListener() { @@ -129,10 +150,12 @@ public class MarkerViewActivity extends AppCompatActivity { private static class CountryAdapter extends MapboxMap.MarkerViewAdapter<CountryMarkerView> { private LayoutInflater inflater; + private MapboxMap mapboxMap; - public CountryAdapter(@NonNull Context context) { + public CountryAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) { super(context); this.inflater = LayoutInflater.from(context); + this.mapboxMap = mapboxMap; } @Nullable @@ -153,12 +176,143 @@ public class MarkerViewActivity extends AppCompatActivity { return convertView; } + @Override + public boolean onSelect(@NonNull final CountryMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) { + convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 0, 360); + rotateAnimator.setDuration(reselectionForViewReuse ? 0 : 350); + rotateAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + convertView.setLayerType(View.LAYER_TYPE_NONE, null); + mapboxMap.selectMarker(marker); + } + }); + rotateAnimator.start(); + + // false indicates that we are calling selectMarker after our animation ourselves + // true will let the system call it for you, which will result in showing an InfoWindow instantly + return false; + } + + @Override + public void onDeselect(@NonNull CountryMarkerView marker, @NonNull final View convertView) { + convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + ObjectAnimator rotateAnimator = ObjectAnimator.ofFloat(convertView, View.ROTATION, 360, 0); + rotateAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + convertView.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + rotateAnimator.start(); + } + private static class ViewHolder { ImageView flag; TextView abbrev; } } + + private static class TextAdapter extends MapboxMap.MarkerViewAdapter<TextMarkerView> { + + private LayoutInflater inflater; + private MapboxMap mapboxMap; + + public TextAdapter(@NonNull Context context, @NonNull MapboxMap mapboxMap) { + super(context); + this.inflater = LayoutInflater.from(context); + this.mapboxMap = mapboxMap; + } + + @Nullable + @Override + public View getView(@NonNull TextMarkerView marker, @Nullable View convertView, @NonNull ViewGroup parent) { + ViewHolder viewHolder; + if (convertView == null) { + viewHolder = new ViewHolder(); + convertView = inflater.inflate(R.layout.view_text_marker, parent, false); + viewHolder.textView = (TextView) convertView.findViewById(R.id.textView); + convertView.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) convertView.getTag(); + } + viewHolder.textView.setText(marker.getText()); + return convertView; + } + + @Override + public boolean onSelect(@NonNull final TextMarkerView marker, @NonNull final View convertView, boolean reselectionForViewReuse) { + animateGrow(marker, convertView, 0); + + // false indicates that we are calling selectMarker after our animation ourselves + // true will let the system call it for you, which will result in showing an InfoWindow instantly + return false; + } + + @Override + public void onDeselect(@NonNull TextMarkerView marker, @NonNull final View convertView) { + animateShrink(convertView, 350); + } + + @Override + public boolean prepareViewForReuse(@NonNull MarkerView marker, @NonNull View convertView) { + // this method is called before a view will be reused, we need to restore view state + // as we have scaled the view in onSelect. If not correctly applied other MarkerView will + // become large since these have been recycled + + // cancel ongoing animation + convertView.animate().cancel(); + + if (marker.isSelected()) { + // shrink view to be able to be reused + animateShrink(convertView, 0); + } + + // true if you want reuse to occur automatically, false if you want to manage this yourself + return true; + } + + private void animateGrow(@NonNull final MarkerView marker, @NonNull final View convertView, int duration) { + convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_up); + animator.setDuration(duration); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + convertView.setLayerType(View.LAYER_TYPE_NONE, null); + mapboxMap.selectMarker(marker); + } + }); + animator.setTarget(convertView); + animator.start(); + } + + private void animateShrink(@NonNull final View convertView, int duration) { + convertView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + Animator animator = AnimatorInflater.loadAnimator(convertView.getContext(), R.animator.scale_down); + animator.setDuration(duration); + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + convertView.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); + animator.setTarget(convertView); + animator.start(); + } + + private static class ViewHolder { + TextView textView; + } + } + + @Override public void onResume() { super.onResume(); diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java index c4ef4a8d13..ab0fd396ea 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/CountryMarkerViewOptions.java @@ -64,6 +64,7 @@ public class CountryMarkerViewOptions extends BaseMarkerViewOptions<CountryMarke out.writeInt(getSelectAnimRes()); out.writeInt(getDeselectAnimRes()); out.writeInt(getRotation()); + out.writeByte((byte) (selected ? 1 :0)); Icon icon = getIcon(); out.writeByte((byte) (icon != null ? 1 : 0)); if (icon != null) { diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java new file mode 100644 index 0000000000..c0a589cb57 --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerView.java @@ -0,0 +1,18 @@ +package com.mapbox.mapboxsdk.testapp.model.annotations; + +import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions; +import com.mapbox.mapboxsdk.annotations.MarkerView; + +public class TextMarkerView extends MarkerView { + + private String text; + + public TextMarkerView(BaseMarkerViewOptions baseMarkerViewOptions, String text) { + super(baseMarkerViewOptions); + this.text = text; + } + + public String getText() { + return text; + } +}
\ No newline at end of file diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java new file mode 100644 index 0000000000..48ab57345e --- /dev/null +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/annotations/TextMarkerViewOptions.java @@ -0,0 +1,91 @@ +package com.mapbox.mapboxsdk.testapp.model.annotations; + +import android.graphics.Bitmap; +import android.os.Parcel; +import android.os.Parcelable; + +import com.mapbox.mapboxsdk.annotations.BaseMarkerViewOptions; +import com.mapbox.mapboxsdk.annotations.Icon; +import com.mapbox.mapboxsdk.annotations.IconFactory; +import com.mapbox.mapboxsdk.geometry.LatLng; + +public class TextMarkerViewOptions extends BaseMarkerViewOptions<TextMarkerView,TextMarkerViewOptions> { + + private String text; + + public TextMarkerViewOptions() { + } + + protected TextMarkerViewOptions(Parcel in) { + position((LatLng) in.readParcelable(LatLng.class.getClassLoader())); + snippet(in.readString()); + title(in.readString()); + flat(in.readByte() != 0); + anchor(in.readFloat(), in.readFloat()); + infoWindowAnchor(in.readFloat(), in.readFloat()); + selectAnimatorResource(in.readInt()); + deselectAnimatorResource(in.readInt()); + rotation(in.readInt()); + if (in.readByte() != 0) { + // this means we have an icon + String iconId = in.readString(); + Bitmap iconBitmap = in.readParcelable(Bitmap.class.getClassLoader()); + Icon icon = IconFactory.recreate(iconId, iconBitmap); + icon(icon); + } + text(in.readString()); + } + + @Override + public TextMarkerViewOptions getThis() { + return this; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeParcelable(getPosition(), flags); + out.writeString(getSnippet()); + out.writeString(getTitle()); + out.writeByte((byte) (isFlat() ? 1 : 0)); + out.writeFloat(getAnchorU()); + out.writeFloat(getAnchorV()); + out.writeFloat(getInfoWindowAnchorU()); + out.writeFloat(getInfoWindowAnchorV()); + out.writeInt(getSelectAnimRes()); + out.writeInt(getDeselectAnimRes()); + out.writeInt(getRotation()); + Icon icon = getIcon(); + out.writeByte((byte) (icon != null ? 1 : 0)); + if (icon != null) { + out.writeString(getIcon().getId()); + out.writeParcelable(getIcon().getBitmap(), flags); + } + out.writeString(text); + } + + @Override + public TextMarkerView getMarker() { + return new TextMarkerView(this, text); + } + + public TextMarkerViewOptions text(String text) { + this.text = text; + return getThis(); + } + + public static final Parcelable.Creator<CountryMarkerViewOptions> CREATOR + = new Parcelable.Creator<CountryMarkerViewOptions>() { + public CountryMarkerViewOptions createFromParcel(Parcel in) { + return new CountryMarkerViewOptions(in); + } + + public CountryMarkerViewOptions[] newArray(int size) { + return new CountryMarkerViewOptions[size]; + } + }; +} diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java index 7d874f21fe..a4b3248f2e 100644 --- a/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java +++ b/platform/android/MapboxGLAndroidSDKTestApp/src/test/java/com/mapbox/mapboxsdk/annotations/MarkerViewTest.java @@ -3,7 +3,6 @@ package com.mapbox.mapboxsdk.annotations; import android.os.Parcelable; import com.mapbox.mapboxsdk.geometry.LatLng; -import com.mapbox.mapboxsdk.testapp.R; import com.mapbox.mapboxsdk.utils.MockParcel; import org.junit.Test; @@ -98,22 +97,6 @@ public class MarkerViewTest { } @Test - public void testSelectAnimRes() { - int animatorRes = R.animator.rotate_360; - MarkerViewOptions markerOptions = new MarkerViewOptions().selectAnimatorResource(animatorRes); - MarkerView marker = markerOptions.getMarker(); - assertEquals("select animator resource should match ", animatorRes, marker.getSelectAnimRes(), 0); - } - - @Test - public void testDeselectAnimRes() { - int animatorRes = R.animator.rotate_360; - MarkerViewOptions markerOptions = new MarkerViewOptions().deselectAnimatorResource(animatorRes); - MarkerView marker = markerOptions.getMarker(); - assertEquals("deselect animator resource should match ", animatorRes, marker.getDeselectAnimRes(), 0); - } - - @Test public void testRotation() { int rotation = 90; MarkerViewOptions markerOptions = new MarkerViewOptions().rotation(rotation); |