Как анимировать маркер через ArrayList точек LatLng?

Я использую Google Maps API V2, чтобы получить местоположение текущего пользователя, и я записываю его маршрут, используя прослушиватель onLocationChanged. Пока пользователь записывает свой маршрут, я сохраняю все обнаруженные LatLngs при каждом изменении местоположения в arraylist. Когда пользователь перестает записывать свой маршрут, я помещаю маркер в первую точку в arraylist. Моя проблема в том, что я хочу анимировать маркер через все точки в arraylist. Может кто-нибудь, пожалуйста, скажите мне, как я могу это сделать?

Следует отметить, что массив не нуждается в сортировке, потому что я записываю точки по мере их поступления. Я попытался использовать цикл for для цикла через массив и отправить значения, но я получаю сообщение об ошибке

Final LatLng startLatLng = proj.fromScreenLocation (startPoint);

Говоря «Неизвестный источник» вместе с исключением NullPointer.

Вот мой код:

case R.id.action_replay: int o; for(o=0; o<oldlocPoints.size(); ++o){ if(--o > 1){lastPos = oldlocPoints.get(--o);} toPos = oldlocPoints.get(++o); animateMarker(markerStart, lastPos, toPos); } return true; 

И вот как я пытаюсь оживить маркеры. Основная трудность, с которой я сталкиваюсь, заключается в том, что в run () мне кажется, что мне нужны значения конечного типа, поэтому я не знаю, как это понравится.

  //Animates marker through the locations saved from the recorded route public void animateMarker(final Marker marker, LatLng lastPos, final LatLng toPos) { final long duration = 1600; final Handler handler = new Handler(); this.lastPos = lastPos; this.toPos = toPos; final long start = SystemClock.uptimeMillis(); final int o; Projection proj = map.getProjection(); Point startPoint = proj.toScreenLocation(lastPos); final LatLng startLatLng = proj.fromScreenLocation(startPoint); Log.d(TAG, "" + lastPos + "" + toPos); final Interpolator interpolator = new AccelerateDecelerateInterpolator(); handler.post(new Runnable() { @Override public void run() { long elapsed = SystemClock.uptimeMillis() - start; float t = interpolator.getInterpolation((float) elapsed / duration); double lng = t * toPos.longitude + (1 - t) * startLatLng.longitude; double lat = t * toPos.latitude + (1 - t) * startLatLng.latitude; markerStart.setPosition(new LatLng(lat, lng)); //markerStart.setPosition(interpolator.interpolate(t, target, replayEnd)); if (t < 1.0) { //Post again 16ms later == 60 frames per second handler.postDelayed(this, 32); } else { //Animation ended } } }); } 

Может кто-нибудь, пожалуйста, помогите мне?

UPDATE Моя ближайшая попытка – это:

 while (i<oldlocPoints.size()){ final long duration = 32; final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); Projection proj = map.getProjection(); final LatLng toPos = oldlocPoints.get(i/3); Point startPoint = proj.toScreenLocation(oldlocPoints.get(i)); final LatLng startLatLng = proj.fromScreenLocation(startPoint); final Interpolator interpolator = new AccelerateDecelerateInterpolator(); handler.post(new Runnable() { @Override public void run() { long elapsed = SystemClock.uptimeMillis() - start; float t = interpolator.getInterpolation((float) elapsed / duration); double lng = t * toPos.longitude + (1 - t) * startLatLng.longitude; double lat = t * toPos.latitude + (1 - t) * startLatLng.latitude; markerStart.setPosition(new LatLng(lat, lng)); //markerStart.setPosition(interpolator.interpolate(t, target, replayEnd)); if (t < 1.0) { //Post again 16ms later == 60 frames per second handler.postDelayed(this, 32); } else { //Animation ended } } }); i++; } 

    Попробуйте этот код :: сначала класс MarkerAnimation:

     public class MarkerAnimation { static GoogleMap map; ArrayList<LatLng> _trips = new ArrayList<>() ; Marker _marker; LatLngInterpolator _latLngInterpolator = new LatLngInterpolator.Spherical(); public void animateLine(ArrayList<LatLng> Trips,GoogleMap map,Marker marker,Context current){ _trips.addAll(Trips); _marker = marker; animateMarker(); } public void animateMarker() { TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() { @Override public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) { return _latLngInterpolator.interpolate(fraction, startValue, endValue); } }; Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position"); ObjectAnimator animator = ObjectAnimator.ofObject(_marker, property, typeEvaluator, _trips.get(0)); //ObjectAnimator animator = ObjectAnimator.o(view, "alpha", 0.0f); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationCancel(Animator animation) { // animDrawable.stop(); } @Override public void onAnimationRepeat(Animator animation) { // animDrawable.stop(); } @Override public void onAnimationStart(Animator animation) { // animDrawable.stop(); } @Override public void onAnimationEnd(Animator animation) { // animDrawable.stop(); if (_trips.size() > 1) { _trips.remove(0); animateMarker(); } } }); animator.setDuration(300); animator.start(); } 

    И _latLngInterpolator, который предварительно написан для вас разработчиками Google:

     public interface LatLngInterpolator { public LatLng interpolate(float fraction, LatLng a, LatLng b); public class Spherical implements LatLngInterpolator { @Override public LatLng interpolate(float fraction, LatLng from, LatLng to) { // http://en.wikipedia.org/wiki/Slerp double fromLat = toRadians(from.latitude); double fromLng = toRadians(from.longitude); double toLat = toRadians(to.latitude); double toLng = toRadians(to.longitude); double cosFromLat = cos(fromLat); double cosToLat = cos(toLat); // Computes Spherical interpolation coefficients. double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng); double sinAngle = sin(angle); if (sinAngle < 1E-6) { return from; } double a = sin((1 - fraction) * angle) / sinAngle; double b = sin(fraction * angle) / sinAngle; // Converts from polar to vector and interpolate. double x = a * cosFromLat * cos(fromLng) + b * cosToLat * cos(toLng); double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng); double z = a * sin(fromLat) + b * sin(toLat); // Converts interpolated vector back to polar. double lat = atan2(z, sqrt(x * x + y * y)); double lng = atan2(y, x); return new LatLng(toDegrees(lat), toDegrees(lng)); } private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng) { // Haversine's formula double dLat = fromLat - toLat; double dLng = fromLng - toLng; return 2 * asin(sqrt(pow(sin(dLat / 2), 2) + cos(fromLat) * cos(toLat) * pow(sin(dLng / 2), 2))); } } } 

    И назовите его на своей карте как:

      MarkerAnimation.animateLine(TripPoints,map,MovingMarker,context);