/* * Copyright (C) 2013 Maciej Górski * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package pl.mg6.android.maps.extensions.impl; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import pl.mg6.android.maps.extensions.AnimationSettings; import pl.mg6.android.maps.extensions.Marker; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.os.SystemClock; import android.view.animation.Interpolator; import com.google.android.gms.maps.model.LatLng; class MarkerAnimator { private Handler handler = new Handler(new Callback() { @Override public boolean handleMessage(Message msg) { calculatePositions(); return true; } }); private Map<DelegatingMarker, AnimationData> queue = new HashMap<DelegatingMarker, AnimationData>(); private void calculatePositions() { long now = SystemClock.uptimeMillis(); Iterator<DelegatingMarker> iterator = queue.keySet().iterator(); while (iterator.hasNext()) { DelegatingMarker marker = iterator.next(); AnimationData data = queue.get(marker); long time = now - data.start; if (time <= 0) { marker.setPositionDuringAnimation(data.from); } else if (time >= data.duration) { marker.setPositionDuringAnimation(data.to); if (data.callback != null) { data.callback.onFinish(marker); } iterator.remove(); } else { float t = ((float) time) / data.duration; t = data.interpolator.getInterpolation(t); double lat = (1.0f - t) * data.from.latitude + t * data.to.latitude; double lng = (1.0f - t) * data.from.longitude + t * data.to.longitude; marker.setPositionDuringAnimation(new LatLng(lat, lng)); } } if (queue.size() > 0) { handler.sendEmptyMessage(0); } } public void animate(DelegatingMarker marker, LatLng from, LatLng to, long start, AnimationSettings settings, Marker.AnimationCallback callback) { AnimationData data = new AnimationData(); data.from = from; data.to = to; data.start = start; data.duration = settings.getDuration(); data.interpolator = settings.getInterpolator(); data.callback = callback; queue.put(marker, data); handler.removeMessages(0); handler.sendEmptyMessage(0); } public void cancelAnimation(DelegatingMarker marker, Marker.AnimationCallback.CancelReason reason) { AnimationData data = queue.remove(marker); if (data != null && data.callback != null) { data.callback.onCancel(marker, reason); } } private static class AnimationData { private LatLng from; private LatLng to; private long start; private long duration; private Interpolator interpolator; private Marker.AnimationCallback callback; } }