我正在创建Google地图当前位置气球覆盖。
我使用android-mapviewballoons此代码来显示气球。
此处当前位置显示正常。当我点击标记时,会出现错误(BalloonOverlayView 49,37行和BalloonItemizedOverlay 86,179,76行)。
我知道错误在哪里,但我不理解那部分,请帮助我
这是LogCat错误
01-31 09:27:46.278: E/AndroidRuntime(4704): FATAL EXCEPTION: main
01-31 09:27:46.278: E/AndroidRuntime(4704): android.view.InflateException: Binary XML file line #28: Error inflating class <unknown>
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.createView(LayoutInflater.java:613)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.onCreateView(LayoutInflater.java:660)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:685)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.sygnet.locationingooglemap.BalloonOverlayView.setupView(BalloonOverlayView.java:49)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.sygnet.locationingooglemap.BalloonOverlayView.<init>(BalloonOverlayView.java:37)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.sygnet.locationingooglemap.BalloonItemizedOverlay.createBalloonOverlayView(BalloonItemizedOverlay.java:86)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.sygnet.locationingooglemap.BalloonItemizedOverlay.createAndDisplayBalloonOverlay(BalloonItemizedOverlay.java:179)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.sygnet.locationingooglemap.BalloonItemizedOverlay.onTap(BalloonItemizedOverlay.java:76)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.google.android.maps.ItemizedOverlay.onTap(ItemizedOverlay.java:453)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.google.android.maps.OverlayBundle.onTap(OverlayBundle.java:83)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.google.android.maps.MapView$1.onSingleTapUp(MapView.java:358)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.google.android.maps.GestureDetector.onTouchEvent(GestureDetector.java:562)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.google.android.maps.MapView.onTouchEvent(MapView.java:685)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.View.dispatchTouchEvent(View.java:7239)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2168)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1903)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2174)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1953)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1405)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.app.Activity.dispatchTouchEvent(Activity.java:2410)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1901)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.View.dispatchPointerEvent(View.java:7419)
01-31 09:27:46.278: E/AndroidRuntime(4704): at an droid.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3220)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3165)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4292)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4271)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4363)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.os.MessageQueue.nativePollOnce(Native Method)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.os.MessageQueue.next(MessageQueue.java:125)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.os.Looper.loop(Looper.java:124)
01-31 09:27:46.278: E/AndroidRuntime(4704): at android.app.ActivityThread.main(ActivityThread.java:5039)
01-31 09:27:46.278: E/AndroidRuntime(4704): at java.lang.reflect.Method.invokeNative(Native Method)
01-31 09:27:46.278: E/AndroidRuntime(4704): at java.lang.reflect.Method.invoke(Method.java:511)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
01-31 09:27:46.278: E/AndroidRuntime(4704): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
01-31 09:27:46.278: E/AndroidRuntime(4704): at dalvik.system.NativeStart.main(Native Method)
01-31 09:27:46.278: E/AndroidRuntime(4704): Caused by: java.lang.reflect.InvocationTargetException
01-31 09:27:46.278: E/AndroidRuntime(4704): at java.lang.reflect.Constructor.constructNative(Native Method)
01-31 09:27:46.278: E/AndroidRuntime(4704): at java.lang.reflect.Constructor.ne
这是BalloonItemizedOverlay.java
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
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) {
mc.animateTo(currentFocusedItem.getPoint());
}
return true;
}
protected BalloonOverlayView<Item> createBalloonOverlayView() {
return new BalloonOverlayView<Item>(getMapView().getContext(), getBalloonBottomOffset());
}
protected MapView getMapView() {
return mapView;
}
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();
//Event Action Down
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int[] states = {android.R.attr.state_pressed};
if (d.setState(states)) {
d.invalidateSelf();
}
startX = event.getX();
startY = event.getY();
return true;
}
//Event Action Up
else if (event.getAction() == MotionEvent.ACTION_UP) {
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;
}
}
};
}
@Override
public Item getFocus() {
return currentFocusedItem;
}
@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;
}
};
}
这是BalloonOverlayView.java
public class BalloonOverlayView<Item extends OverlayItem> extends FrameLayout {
private LinearLayout layout;
private TextView title;
MainActivity main;
// private CharSequence tvLocation;
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);
}
protected void setupView(Context context, 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);
// title.setText(tvLocation);
}
public void setData(Item item) {
layout.setVisibility(VISIBLE);
setBalloonData(item, layout);
}
protected void setBalloonData(Item item, ViewGroup parent) {
if (item.getTitle() != null) {
title.setVisibility(VISIBLE);
title.setText(item.getTitle());
} else {
title.setText("");
title.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);
}
}
}