|
最近在论坛里面看到很多人想实现现在很多地图应用上那种在地图上显示我的位置气泡,点击该气泡还能弹出一个详情对话框的气泡这种需求!正好前几天做的一个应用里面包含了这样一个项目,所以就顺手做了一个demo来和大家分享一下!
下面是我截的一个高德地图的图片。
废话不多说了,先上我做的demo里面的截图,让大家比对一下效果:
看到了吧!你可以点击红色小图标气泡,那么在其上方出现其位置的详情信息气泡,那个详情气泡也可以点击哦!那这样的话就可以实现很多需求了,比如我当前弹出来的是关于房产的简略信息气泡,那么点击它就可以跳转到该房产的具体详情页面了!非常强大吧!目前我好像还没有见过有人介绍过百度地图这种效果的!
让你轻轻松松实现百度地图终极气泡!
下面上代码:
1、这是一个气泡覆盖物view,在这里你可以定义你想要弹出来的任何样式的详情气泡
public class BalloonOverlayView<Item extends OverlayItem> extends FrameLayout {
private LinearLayout layout;
private TextView title;
private TextView snippet;
/**
* Create a new BalloonOverlayView.
*
* @param context - The activity context.
* @param balloonBottomOffset - The bottom padding (in pixels) to be applied
* when rendering this view.
*/
public BalloonOverlayView(Context context, int balloonBottomOffset) {
super(context);
setPadding(10, 0, 10, balloonBottomOffset);
layout = new LimitLinearLayout(context);
layout.setVisibility(VISIBLE);
setupView(context, layout);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.NO_GRAVITY;
addView(layout, params);
}
/**
* Inflate and initialize the BalloonOverlayView UI. Override this method
* to provide a custom view/layout for the balloon.
*
* @param context - The activity context.
* @param parent - The root layout into which you must inflate your view.
*/
protected void setupView(Context context, final ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.balloon_overlay, parent);
title = (TextView) v.findViewById(R.id.balloon_item_title);
snippet = (TextView) v.findViewById(R.id.balloon_item_snippet);
}
/**
* Sets the view data from a given overlay item.
*
* @param item - The overlay item containing the relevant view data.
*/
public void setData(Item item) {
layout.setVisibility(VISIBLE);
setBalloonData(item, layout);
}
/**
* Sets the view data from a given overlay item. Override this method to create
* your own data/view mappings.
*
* @param item - The overlay item containing the relevant view data.
* @param parent - The parent layout for this BalloonOverlayView.
*/
protected void setBalloonData(Item item, ViewGroup parent) {
if (item.getTitle() != null) {
title.setVisibility(VISIBLE);
title.setText(item.getTitle());
} else {
title.setText("");
title.setVisibility(GONE);
}
if (item.getSnippet() != null) {
snippet.setVisibility(VISIBLE);
snippet.setText(item.getSnippet());
} else {
snippet.setText("");
snippet.setVisibility(GONE);
}
}
private class LimitLinearLayout extends LinearLayout {
private static final int MAX_WIDTH_DP = 280;
final float SCALE = getContext().getResources().getDisplayMetrics().density;
public LimitLinearLayout(Context context) {
super(context);
}
public LimitLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int mode = MeasureSpec.getMode(widthMeasureSpec);
int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
int adjustedMaxWidth = (int)(MAX_WIDTH_DP * SCALE + 0.5f);
int adjustedWidth = Math.min(measuredWidth, adjustedMaxWidth);
int adjustedWidthMeasureSpec = MeasureSpec.makeMeasureSpec(adjustedWidth, mode);
super.onMeasure(adjustedWidthMeasureSpec, heightMeasureSpec);
}
}
}
2、
//这是一个详情气泡的抽象类,继承这个类的话,你就可以管理多个弹出的详情气泡了,在这里实现点击了。
public abstract class BalloonItemizedOverlay<Item extends OverlayItem> extends ItemizedOverlay<Item> {
private static final long BALLOON_INFLATION_TIME = 300;
private static Handler handler = new Handler();
private MapView mapView;
private BalloonOverlayView<Item> balloonView;
private View clickRegion;
private View closeRegion;
private int viewOffset;
final MapController mc;
private Item currentFocusedItem;
private int currentFocusedIndex;
private boolean showClose = true;
private boolean showDisclosure = false;
private boolean snapToCenter = true;
private static boolean isInflating = false;
public BalloonItemizedOverlay(Drawable defaultMarker, MapView mapView) {
super(defaultMarker);
this.mapView = mapView;
viewOffset = 0;
mc = mapView.getController();
}
public void setBalloonBottomOffset(int pixels) {
viewOffset = pixels;
}
public int getBalloonBottomOffset() {
return viewOffset;
}
protected boolean onBalloonTap(int index, Item item) {
return false;
}
protected void onBalloonOpen(int index) {}
@Override
//protected final boolean onTap(int index) {
public final boolean onTap(int index) {
handler.removeCallbacks(finishBalloonInflation);
isInflating = true;
handler.postDelayed(finishBalloonInflation, BALLOON_INFLATION_TIME);
currentFocusedIndex = index;
currentFocusedItem = createItem(index);
setLastFocusedIndex(index);
onBalloonOpen(index);
createAndDisplayBalloonOverlay();
if (snapToCenter) {
animateTo(index, currentFocusedItem.getPoint());
}
return true;
}
protected void animateTo(int index, GeoPoint center) {
mc.animateTo(center);
}
protected BalloonOverlayView<Item> createBalloonOverlayView() {
return new BalloonOverlayView<Item>(getMapView().getContext(), getBalloonBottomOffset());
}
protected MapView getMapView() {
return mapView;
}
public void bringBalloonToFront() {
if (balloonView != null) {
balloonView.bringToFront();
}
}
public void hideBalloon() {
if (balloonView != null) {
balloonView.setVisibility(View.GONE);
}
currentFocusedItem = null;
}
private void hideOtherBalloons(List<Overlay> overlays) {
for (Overlay overlay : overlays) {
if (overlay instanceof BalloonItemizedOverlay<?> && overlay != this) {
((BalloonItemizedOverlay<?>) overlay).hideBalloon();
}
}
}
public void hideAllBalloons() {
if (!isInflating) {
List<Overlay> mapOverlays = mapView.getOverlays();
if (mapOverlays.size() > 1) {
hideOtherBalloons(mapOverlays);
}
hideBalloon();
}
}
private OnTouchListener createBalloonTouchListener() {
return new OnTouchListener() {
float startX;
float startY;
public boolean onTouch(View v, MotionEvent event) {
View l = ((View) v.getParent()).findViewById(R.id.balloon_main_layout);
Drawable d = l.getBackground();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (d != null) {
int[] states = {android.R.attr.state_pressed};
if (d.setState(states)) {
d.invalidateSelf();
}
}
startX = event.getX();
startY = event.getY();
return true;
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (d != null) {
int newStates[] = {};
if (d.setState(newStates)) {
d.invalidateSelf();
}
}
if (Math.abs(startX - event.getX()) < 40 &&
Math.abs(startY - event.getY()) < 40 ) {
// call overridden method
onBalloonTap(currentFocusedIndex, currentFocusedItem);
}
return true;
} else {
return false;
}
}
};
}
/* (non-Javadoc)
* @see com.google.android.maps.ItemizedOverlay#getFocus()
*/
@Override
public Item getFocus() {
return currentFocusedItem;
}
/* (non-Javadoc)
* @see com.google.android.maps.ItemizedOverlay#setFocus(Item)
*/
@Override
public void setFocus(Item item) {
super.setFocus(item);
currentFocusedIndex = getLastFocusedIndex();
currentFocusedItem = item;
if (currentFocusedItem == null) {
hideBalloon();
} else {
createAndDisplayBalloonOverlay();
}
}
private boolean createAndDisplayBalloonOverlay(){
boolean isRecycled;
if (balloonView == null) {
balloonView = createBalloonOverlayView();
clickRegion = (View) balloonView.findViewById(R.id.balloon_inner_layout);
clickRegion.setOnTouchListener(createBalloonTouchListener());
closeRegion = (View) balloonView.findViewById(R.id.balloon_close);
if (closeRegion != null) {
if (!showClose) {
closeRegion.setVisibility(View.GONE);
} else {
closeRegion.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hideBalloon();
}
});
}
}
if (showDisclosure && !showClose) {
View v = balloonView.findViewById(R.id.balloon_disclosure);
if (v != null) {
v.setVisibility(View.VISIBLE);
}
}
isRecycled = false;
} else {
isRecycled = true;
}
balloonView.setVisibility(View.GONE);
List<Overlay> mapOverlays = mapView.getOverlays();
if (mapOverlays.size() > 1) {
hideOtherBalloons(mapOverlays);
}
if (currentFocusedItem != null)
balloonView.setData(currentFocusedItem);
GeoPoint point = currentFocusedItem.getPoint();
MapView.LayoutParams params = new MapView.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, point,
MapView.LayoutParams.BOTTOM_CENTER);
params.mode = MapView.LayoutParams.MODE_MAP;
balloonView.setVisibility(View.VISIBLE);
if (isRecycled) {
balloonView.setLayoutParams(params);
} else {
mapView.addView(balloonView, params);
}
return isRecycled;
}
public void setShowClose(boolean showClose) {
this.showClose = showClose;
}
public void setShowDisclosure(boolean showDisclosure) {
this.showDisclosure = showDisclosure;
}
public void setSnapToCenter(boolean snapToCenter) {
this.snapToCenter = snapToCenter;
}
public static boolean isInflating() {
return isInflating;
}
private static Runnable finishBalloonInflation = new Runnable() {
public void run() {
isInflating = false;
}
};
}
3、
/** 实现详情气泡的点击事件
* @author asus
*
*/
public class SimpleItemizedOverlay extends BalloonItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> m_overlays = new ArrayList<OverlayItem>();
private Context c;
public SimpleItemizedOverlay(Drawable defaultMarker, MapView mapView) {
super(boundCenter(defaultMarker), mapView);
c = mapView.getContext();
}
public void addOverlay(OverlayItem overlay) {
m_overlays.add(overlay);
populate();
}
@Override
protected OverlayItem createItem(int i) {
return m_overlays.get(i);
}
@Override
public int size() {
return m_overlays.size();
}
@Override
protected boolean onBalloonTap(int index, OverlayItem item) {
Toast.makeText(c, "您点击的是第 " + index+"个气泡",
Toast.LENGTH_LONG).show();
return true;
}
}
4、用法也很简单:
//第一步:先进行初始化
SimpleItemizedOverlay itemizedOverlay = new SimpleItemizedOverlay(marker, mMapView);
//第二步:添加覆盖物到图层区
GeoPoint p1 = new GeoPoint((int) (infos.get(0).getLatitude() * 1E6), (int) (infos.get(0).getLongtitude() * 1E6));
OverlayItem overlayItem = new OverlayItem(p1, "富力天朗明居", "(地理位置优越,欢迎选购!)");
itemizedOverlay.addOverlay(overlayItem);
GeoPoint p2 = new GeoPoint((int) (infos.get(1).getLatitude() * 1E6), (int) (infos.get(0).getLongtitude() * 1E6));
OverlayItem overlayItem1 = new OverlayItem(p2, "顺德碧桂园东苑", "(地理位置优越,欢迎选购!)");
itemizedOverlay.addOverlay(overlayItem1);
GeoPoint p3 = new GeoPoint((int) (infos.get(2).getLatitude() * 1E6), (int) (infos.get(0).getLongtitude() * 1E6));
OverlayItem overlayItem2 = new OverlayItem(p3, "广州雅居乐花园", "(地理位置优越,欢迎选购!)");
itemizedOverlay.addOverlay(overlayItem2);
//添加到图层中
mapOverlays.add(itemizedOverlay);
//==============================================================================================================
题外话:其实这是根据github上面一个关于googlemap的开源项目叫mapviewballoons改良过来的!我只是把它弄到了百度地图上面。
我知道很多人不知道怎么去github那些英文网站上找开源项目,一是因为英文不好,嫌麻烦,二是不知道该看哪些,三是即使看见了下载下来也会因为导入eclipse出了各种错看不到最后的运行效果图而错失了一个好的开源项目。
因此,我做了一个介绍目前最新、最实用、最适合移植到项目中去的电子地图的应用软件叫做sitemapIMS地图开发平台(名字太土了!呵呵!),里面收录了常用的地图开发应用组件,款开源项目,分为视图、组件、工具库、开源项目四大类,每个项目都做了下中文翻译(有的项目已经广为认知了!),并提供了项目的最终运行效果图,那样你就可以根据效果图去决定那个是你所需要的项目了!
|
|