/******************************************************************************* * Copyleft 2013 Massimiliano Leone - massimiliano.leone@iubris.net . * * PopulateMapAsyncTask.java is part of 'Ulysses'. * * 'Ulysses' is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * 'Ulysses' is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with 'Ulysses'; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ package net.iubris.ulysses.ui.tasks.populate.map._base; import java.util.HashMap; import java.util.List; import java.util.Map; import net.iubris.ulysses.model.Place; import net.iubris.ulysses.tasks._base.AbstractUlyssesTask; import net.iubris.ulysses.ui.icons.sieve.Sieve; import net.iubris.ulysses.ui.map.marker.infowindow.UlyssesInfowindowAdapter; import net.iubris.ulysses.ui.tasks.populate.map._base.exceptions.LocationNullException; import net.iubris.ulysses.ui.tasks.populate.map._utils.LocationUtils; import net.iubris.ulysses.ui.toast.utils.UIUtils; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.Bitmap; import android.os.Build; import android.support.v4.app.Fragment; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.GoogleMap.OnMapLoadedCallback; import com.google.android.gms.maps.model.BitmapDescriptorFactory; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.LatLngBounds; import com.google.android.gms.maps.model.LatLngBounds.Builder; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; /** * abstract class for populate map with search result * */ public abstract class AbstractPopulateMapTask extends AbstractUlyssesTask implements PopulateMapTask { protected static int LATLNG_BOUNDS_PADDING = 23; protected final GoogleMap map; protected final Fragment mapFragment; protected final Map<String, Place> placeByMarkerIdMap; protected final Map<String, Marker> markerByPlaceIdMap; protected final Activity activity; private final Sieve sieve; private LatLngBounds latLngBounds; protected AbstractPopulateMapTask(Activity activity, GoogleMap map, Fragment mapFragment, Sieve sieve) { super(activity); this.activity = activity; this.map = map; // Ln.d("map: "+map); this.mapFragment = mapFragment; this.sieve = sieve; this.placeByMarkerIdMap = new HashMap<String, Place>(); this.markerByPlaceIdMap = new HashMap<String, Marker>(); } @Override public Place findPlaceByMarkerId(String id) { return placeByMarkerIdMap.get(id); } @Override public Marker findMarkerByPlaceEnhancedId(String id) { return markerByPlaceIdMap.get(id); } protected void populateOverlayFromResult(List<Place> placeHeres) { Builder boundsBuilder = createBoundsBuilder(placeHeres); buildBoundsAndZoom(boundsBuilder); } private Builder createBoundsBuilder(final List<Place> placeHeres) { final Builder boundsBuilder = new LatLngBounds.Builder(); clearMarkers(); for (Place place: placeHeres) { MarkerOptions markerOptions = new MarkerOptions(); // Bitmap bitmap = getSieve().find(placeHere.getPlace()); Bitmap bitmap = sieve.find(place); LatLng locationToLatLng = LocationUtils.locationToLatLng( place.getLocation() ); String placeName = place.getPlaceName(); markerOptions.position( locationToLatLng ) .title( placeName ) .snippet( place.getRating() +"") .draggable(false); if (bitmap!=null) markerOptions.icon( BitmapDescriptorFactory.fromBitmap( bitmap ) ); Marker marker = map.addMarker(markerOptions); // dropPinEffect( marker, new LatLngInterpolator.Linear() ); // try { Thread.sleep(200); } catch (InterruptedException e) {} placeByMarkerIdMap.put(marker.getId(), place); markerByPlaceIdMap.put( place.getPlaceId(), marker); boundsBuilder.include(markerOptions.getPosition()); } return boundsBuilder; } protected void buildBoundsAndZoom(Builder boundsBuilder) { latLngBounds = boundsBuilder.build(); map.setOnMapLoadedCallback(onMapLoadedCallback); } /*private void dropPinEffect(final Marker marker, final LatLngInterpolator latLngInterpolator) { final Handler handler = new Handler(); final long start = SystemClock.uptimeMillis(); final long duration = 1500; final Interpolator interpolator = new BounceInterpolator(); handler.post(new Runnable() { @Override public void run() { marker.setVisible(true); long elapsed = SystemClock.uptimeMillis() - start; float t = Math.max(1 - interpolator.getInterpolation((float) elapsed / duration), 0); t = elapsed / duration; // marker.setAnchor(0.5f, 1.0f + 14 * t); // LatLng position = marker.getPosition(); LatLng finalPosition = marker.getPosition(); LatLng startPosition = new LatLng( finalPosition.latitude+0.00001, finalPosition.longitude) ; marker.setPosition( latLngInterpolator.interpolate(interpolator.getInterpolation(t), startPosition, finalPosition )); if (t < duration) { // Post again 15ms later. handler.postDelayed(this, 15); } else { marker.showInfoWindow(); } } }); }*/ /*public interface LatLngInterpolator { public LatLng interpolate(float fraction, LatLng a, LatLng b); public class Linear implements LatLngInterpolator { @Override public LatLng interpolate(float fraction, LatLng a, LatLng b) { double lat = (b.latitude - a.latitude) * fraction + a.latitude; double lng = (b.longitude - a.longitude) * fraction + a.longitude; return new LatLng(lat, lng); } } }*/ protected void clearMarkers() { map.clear(); markerByPlaceIdMap.clear(); placeByMarkerIdMap.clear(); } protected void autoZoom(final LatLngBounds latLngBounds) { final View mapView = mapFragment.getView(); if ((mapView.getWidth() > 0) && (mapView.getHeight()>0)) { if (mapView.getViewTreeObserver().isAlive()) { mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @SuppressWarnings("deprecation") @SuppressLint("NewApi") // We check which build version we are using. @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); } else { mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } // map.animateCamera(CameraUpdateFactory.zoomTo(21.0f)); map.animateCamera( CameraUpdateFactory.newLatLngBounds(latLngBounds, LATLNG_BOUNDS_PADDING) , new GoogleMap.CancelableCallback() { @Override public void onFinish() { // map.animateCamera(CameraUpdateFactory.zoomTo(21f)); } @Override public void onCancel() {} } ); } }); } } } OnMapLoadedCallback onMapLoadedCallback = new OnMapLoadedCallback() { @Override public void onMapLoaded() { autoZoom(latLngBounds); } }; @Override protected void onSuccess(List<Place> places) throws Exception { activity.setProgress(66); populateOverlayFromResult(places); activity.setProgress(100); activity.setProgressBarVisibility(false); map.setInfoWindowAdapter( new UlyssesInfowindowAdapter(activity) ); } protected void onException(LocationNullException arg0) throws RuntimeException { UIUtils.showShortToast("location null", context); super.onException(arg0); } }