osmdroid API解读(十三)
osmdroid-android org.osmdroid.views.overlay.infowindow包
前面介绍的Marker Polygon Polyline可以再点击的时候弹出InfoWindow,本包就是封装InfoWindow的类。
1. InfoWindow
InfoWindow是一个可弹出的视图,可以在MapView中显示,并与IGeoPoint关联。
public abstract class InfoWindow {
protected View mView;
protected boolean mIsVisible;
protected MapView mMapView;
...
//Abstract methods to implement in sub-classes:
public abstract void onOpen(Object item);
public abstract void onClose();
}
2. BasicInfoWindow
为OverlayWithIW类实现的默认的InfoWindow。可以处理一个title、一个description、一个description信息。在弹出框上点击将关闭弹出窗口。
public class BasicInfoWindow extends InfoWindow {
/**
* resource id value meaning "undefined resource id"
*/
public static final int UNDEFINED_RES_ID = 0;
static int mTitleId=UNDEFINED_RES_ID,
mDescriptionId=UNDEFINED_RES_ID,
mSubDescriptionId=UNDEFINED_RES_ID,
mImageId=UNDEFINED_RES_ID; //resource ids
private static void setResIds(Context context){
String packageName = context.getPackageName(); //get application package name
mTitleId = context.getResources().getIdentifier("id/bubble_title", null, packageName);
mDescriptionId = context.getResources().getIdentifier("id/bubble_description", null, packageName);
mSubDescriptionId = context.getResources().getIdentifier("id/bubble_subdescription", null, packageName);
mImageId = context.getResources().getIdentifier("id/bubble_image", null, packageName);
if (mTitleId == UNDEFINED_RES_ID || mDescriptionId == UNDEFINED_RES_ID
|| mSubDescriptionId == UNDEFINED_RES_ID || mImageId == UNDEFINED_RES_ID) {
Log.e(IMapView.LOGTAG, "BasicInfoWindow: unable to get res ids in "+packageName);
}
}
public BasicInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
if (mTitleId == UNDEFINED_RES_ID)
setResIds(mapView.getContext());
//default behavior: close it when clicking on the bubble:
mView.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_UP)
close();
return true;
}
});
}
@Override public void onOpen(Object item) {
OverlayWithIW overlay = (OverlayWithIW)item;
String title = overlay.getTitle();
if (title == null)
title = "";
if (mView==null) {
Log.w(IMapView.LOGTAG, "Error trapped, BasicInfoWindow.open, mView is null!");
return;
}
TextView temp=((TextView)mView.findViewById(mTitleId /*R.id.title*/));
if (temp!=null) temp.setText(title);
String snippet = overlay.getSnippet();
if (snippet == null)
snippet = "";
Spanned snippetHtml = Html.fromHtml(snippet);
((TextView)mView.findViewById(mDescriptionId /*R.id.description*/)).setText(snippetHtml);
//handle sub-description, hidding or showing the text view:
TextView subDescText = (TextView)mView.findViewById(mSubDescriptionId);
String subDesc = overlay.getSubDescription();
if (subDesc != null && !("".equals(subDesc))){
subDescText.setText(Html.fromHtml(subDesc));
subDescText.setVisibility(View.VISIBLE);
} else {
subDescText.setVisibility(View.GONE);
}
}
@Override public void onClose() {
//by default, do nothing
}
}
3. MarkerInfoWindow
MarkerInfoWindow为Marker提供的一个默认的弹出框。它可以处理R.id.bubble_title 、R.id.bubble_subdescription、R.id.bubble_description、R.id.bubble_image四种类型的数据。
public class MarkerInfoWindow extends BasicInfoWindow {
protected Marker mMarkerRef; //reference to the Marker on which it is opened. Null if none.
/**
* @param layoutResId layout that must contain these ids: bubble_title,bubble_description,
* bubble_subdescription, bubble_image
* @param mapView
*/
public MarkerInfoWindow(int layoutResId, MapView mapView) {
super(layoutResId, mapView);
//mMarkerRef = null;
}
/**
* reference to the Marker on which it is opened. Null if none.
* @return
*/
public Marker getMarkerReference(){
return mMarkerRef;
}
@Override public void onOpen(Object item) {
super.onOpen(item);
mMarkerRef = (Marker)item;
if (mView==null) {
Log.w(IMapView.LOGTAG, "Error trapped, MarkerInfoWindow.open, mView is null!");
return;
}
//handle image
ImageView imageView = (ImageView)mView.findViewById(mImageId /*R.id.image*/);
Drawable image = mMarkerRef.getImage();
if (image != null){
imageView.setImageDrawable(image); //or setBackgroundDrawable(image)?
imageView.setVisibility(View.VISIBLE);
} else
imageView.setVisibility(View.GONE);
}
@Override public void onClose() {
super.onClose();
mMarkerRef = null;
//by default, do nothing else
}
}
osmdroid-android org.osmdroid.views.overlay.gridlines 包
1. LatLonGridlineOverlay
在MapView上显示经纬度线的Overlay。
public class LatLonGridlineOverlay {
...
}
osmdroid-android org.osmdroid.views.overlay.gestures包
1. RotationGestureDetector
这个类用于osmdroid内部,如果监听的话最好使用RotationListener。如果你监听的是MapView的旋转可以用MapView#setMapListener(MapListener)来监听,用MapView#getMapOrientation()来检查值。
public class RotationGestureDetector {
public interface RotationListener {
public void onRotate(float deltaAngle);
}
protected float mRotation;
private RotationListener mListener;
public RotationGestureDetector(RotationListener listener) {
mListener = listener;
}
private static float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
public void onTouch(MotionEvent e) {
if (e.getPointerCount() != 2)
return;
if (e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN) {
mRotation = rotation(e);
}
float rotation = rotation(e);
float delta = rotation - mRotation;
mRotation += delta;
mListener.onRotate(delta);
}
}
2. RotationGestureOverlay
用于检测旋转手势,并旋转所有的Overlay。
public class RotationGestureOverlay extends Overlay implements
RotationGestureDetector.RotationListener, IOverlayMenuProvider
{
private final static boolean SHOW_ROTATE_MENU_ITEMS = false;
private final static int MENU_ENABLED = getSafeMenuId();
private final static int MENU_ROTATE_CCW = getSafeMenuId();
private final static int MENU_ROTATE_CW = getSafeMenuId();
private final RotationGestureDetector mRotationDetector;
private MapView mMapView;
private boolean mOptionsMenuEnabled = true;
/** use {@link #RotationGestureOverlay(MapView)} instead. */
@Deprecated
public RotationGestureOverlay(Context context, MapView mapView) {
this(mapView);
}
public RotationGestureOverlay(MapView mapView)
{
super();
mMapView = mapView;
mRotationDetector = new RotationGestureDetector(this);
}
@Override
public void draw(Canvas c, MapView osmv, boolean shadow) {
// No drawing necessary
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
if (this.isEnabled()) {
mRotationDetector.onTouch(event);
}
return super.onTouchEvent(event, mapView);
}
long timeLastSet=0L;
final long deltaTime=25L;
float currentAngle=0f;
@Override
public void onRotate(float deltaAngle)
{
currentAngle+=deltaAngle;
if (System.currentTimeMillis() - deltaTime > timeLastSet){
timeLastSet = System.currentTimeMillis();
mMapView.setMapOrientation(mMapView.getMapOrientation() + currentAngle);
}
}
@Override
public void onDetach(MapView map){
mMapView=null;
}
@Override
public boolean isOptionsMenuEnabled()
{
return mOptionsMenuEnabled;
}
@Override
public boolean onCreateOptionsMenu(Menu pMenu, int pMenuIdOffset, MapView pMapView)
{
pMenu.add(0, MENU_ENABLED + pMenuIdOffset, Menu.NONE, "Enable rotation").setIcon(
android.R.drawable.ic_menu_info_details);
if (SHOW_ROTATE_MENU_ITEMS) {
pMenu.add(0, MENU_ROTATE_CCW + pMenuIdOffset, Menu.NONE,
"Rotate maps counter clockwise").setIcon(android.R.drawable.ic_menu_rotate);
pMenu.add(0, MENU_ROTATE_CW + pMenuIdOffset, Menu.NONE, "Rotate maps clockwise")
.setIcon(android.R.drawable.ic_menu_rotate);
}
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem pItem, int pMenuIdOffset, MapView pMapView)
{
if (pItem.getItemId() == MENU_ENABLED + pMenuIdOffset) {
if (this.isEnabled()) {
mMapView.setMapOrientation(0);
this.setEnabled(false);
} else {
this.setEnabled(true);
return true;
}
} else if (pItem.getItemId() == MENU_ROTATE_CCW + pMenuIdOffset) {
mMapView.setMapOrientation(mMapView.getMapOrientation() - 10);
} else if (pItem.getItemId() == MENU_ROTATE_CW + pMenuIdOffset) {
mMapView.setMapOrientation(mMapView.getMapOrientation() + 10);
}
return false;
}
@Override
public boolean onPrepareOptionsMenu(final Menu pMenu, final int pMenuIdOffset, final MapView pMapView)
{
pMenu.findItem(MENU_ENABLED + pMenuIdOffset).setTitle(
this.isEnabled() ? "Disable rotation" : "Enable rotation");
return false;
}
@Override
public void setOptionsMenuEnabled(boolean enabled)
{
mOptionsMenuEnabled = enabled;
}
}