// Created by plusminus on 17:45:56 - 25.09.2008
package org.osmdroid.views;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import microsoft.mappoint.TileSystem;
import org.metalev.multitouch.controller.MultiTouchController;
import org.metalev.multitouch.controller.MultiTouchController.MultiTouchObjectCanvas;
import org.metalev.multitouch.controller.MultiTouchController.PointInfo;
import org.metalev.multitouch.controller.MultiTouchController.PositionAndScale;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.api.IMapController;
import org.osmdroid.api.IMapView;
import org.osmdroid.events.MapListener;
import org.osmdroid.events.ScrollEvent;
import org.osmdroid.events.ZoomEvent;
import org.osmdroid.tileprovider.MapTileProviderArray;
import org.osmdroid.tileprovider.MapTileProviderBase;
import org.osmdroid.tileprovider.MapTileProviderBasic;
import org.osmdroid.tileprovider.modules.MapTileModuleProviderBase;
import org.osmdroid.tileprovider.tilesource.IStyledTileSource;
import org.osmdroid.tileprovider.tilesource.ITileSource;
import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
import org.osmdroid.tileprovider.util.SimpleInvalidationHandler;
import org.osmdroid.util.BoundingBoxE6;
import org.osmdroid.util.BoundingBox;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.util.GeometryMath;
import org.osmdroid.views.overlay.DefaultOverlayManager;
import org.osmdroid.views.overlay.Overlay;
import org.osmdroid.views.overlay.OverlayManager;
import org.osmdroid.views.overlay.TilesOverlay;
import org.osmdroid.views.util.constants.MapViewConstants;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Scroller;
import android.widget.ZoomButtonsController;
import android.widget.ZoomButtonsController.OnZoomListener;
/**
* This is the primary view for osmdroid
*
* @since the begining
*/
public class MapView extends ViewGroup implements IMapView, MapViewConstants,
MultiTouchObjectCanvas<Object> {
// ===========================================================
// Constants
// ===========================================================
private static final double ZOOM_SENSITIVITY = 1.0;
private static final double ZOOM_LOG_BASE_INV = 1.0 / Math.log(2.0 / ZOOM_SENSITIVITY);
private static Method sMotionEventTransformMethod;
// ===========================================================
// Fields
// ===========================================================
/** Current zoom level for map tiles. */
private int mZoomLevel = 0;
private OverlayManager mOverlayManager;
protected Projection mProjection;
private TilesOverlay mMapOverlay;
private final GestureDetector mGestureDetector;
/** Handles map scrolling */
private final Scroller mScroller;
protected boolean mIsFlinging;
protected final AtomicInteger mTargetZoomLevel = new AtomicInteger();
protected final AtomicBoolean mIsAnimating = new AtomicBoolean(false);
protected Integer mMinimumZoomLevel;
protected Integer mMaximumZoomLevel;
private final MapController mController;
private final ZoomButtonsController mZoomController;
private boolean mEnableZoomController = false;
private MultiTouchController<Object> mMultiTouchController;
protected float mMultiTouchScale = 1.0f;
protected PointF mMultiTouchScalePoint = new PointF();
protected MapListener mListener;
// For rotation
private float mapOrientation = 0;
private final Rect mInvalidateRect = new Rect();
protected BoundingBox mScrollableAreaBoundingBox;
protected Rect mScrollableAreaLimit;
private MapTileProviderBase mTileProvider;
private Handler mTileRequestCompleteHandler;
private boolean mTilesScaledToDpi = false;
final Matrix mRotateScaleMatrix = new Matrix();
final Point mRotateScalePoint = new Point();
/* a point that will be reused to lay out added views */
private final Point mLayoutPoint = new Point();
// Keep a set of listeners for when the maps have a layout
private final LinkedList<OnFirstLayoutListener> mOnFirstLayoutListeners = new LinkedList<MapView.OnFirstLayoutListener>();
/* becomes true once onLayout has been called for the first time i.e. map is ready to go. */
private boolean mLayoutOccurred = false;
public interface OnFirstLayoutListener {
/**
* this generally means that the map is ready to go
* @param v
* @param left
* @param top
* @param right
* @param bottom
*/
void onFirstLayout(View v, int left, int top, int right, int bottom);
}
// ===========================================================
// Constructors
// ===========================================================
protected MapView(final Context context,
MapTileProviderBase tileProvider,
final Handler tileRequestCompleteHandler, final AttributeSet attrs) {
super(context, attrs);
if(isInEditMode()){
mTileRequestCompleteHandler=null;
mController=null;
mZoomController=null;
mScroller=null;
mGestureDetector=null;
return;
}
this.mController = new MapController(this);
this.mScroller = new Scroller(context);
if (tileProvider == null) {
final ITileSource tileSource = getTileSourceFromAttributes(attrs);
tileProvider = isInEditMode()
? new MapTileProviderArray(tileSource, null, new MapTileModuleProviderBase[0])
: new MapTileProviderBasic(context.getApplicationContext(), tileSource);
}
mTileRequestCompleteHandler = tileRequestCompleteHandler == null
? new SimpleInvalidationHandler(this)
: tileRequestCompleteHandler;
mTileProvider = tileProvider;
mTileProvider.setTileRequestCompleteHandler(mTileRequestCompleteHandler);
updateTileSizeForDensity(mTileProvider.getTileSource());
this.mMapOverlay = new TilesOverlay(mTileProvider, context);
mOverlayManager = new DefaultOverlayManager(mMapOverlay);
if (isInEditMode()) {
mZoomController = null;
} else {
mZoomController = new ZoomButtonsController(this);
mZoomController.setOnZoomListener(new MapViewZoomListener());
}
mGestureDetector = new GestureDetector(context, new MapViewGestureDetectorListener());
mGestureDetector.setOnDoubleTapListener(new MapViewDoubleClickListener());
}
/**
* Constructor used by XML layout resource (uses default tile source).
*/
public MapView(final Context context, final AttributeSet attrs) {
this(context, null, null, attrs);
}
public MapView(final Context context) {
this(context, null, null, null);
}
public MapView(final Context context,
final MapTileProviderBase aTileProvider) {
this(context, aTileProvider, null);
}
public MapView(final Context context,
final MapTileProviderBase aTileProvider,
final Handler tileRequestCompleteHandler) {
this(context, aTileProvider, tileRequestCompleteHandler,
null);
}
// ===========================================================
// Getter & Setter
// ===========================================================
@Override
public IMapController getController() {
return this.mController;
}
/**
* You can add/remove/reorder your Overlays using the List of {@link Overlay}. The first (index
* 0) Overlay gets drawn first, the one with the highest as the last one.
*/
public List<Overlay> getOverlays() {
return this.getOverlayManager().overlays();
}
public OverlayManager getOverlayManager() {
return mOverlayManager;
}
pu
评论1
最新资源