- Android
- 2011-12-21 - 更新:2011-12-22
この記事は最終更新日から1年以上経過しています。
GoogleMapにアイコンを表示し、タップすると何らかの処理をしたいとき、通常のonTapメソッドで処理を実行しようとすると、地図の拡大縮小時、アイコンに指が触れているとタップされたことになってしまいます。
これを回避するために、ジェスチャーリスナーを実装し、シングルタップアップにて処理をするようにします。
android.view.GestureDetector.OnGestureListener
public class PinItemizedOverlay extends ItemizedOverlay<OverlayItem> implements OnGestureListener { private List<GeoPoint> points = new ArrayList<GeoPoint>(); private Context context; private GestureDetector gestureDetector = null; private MapView mMapView; private Drawable defaultMarker; public PinItemizedOverlay(Drawable defaultMarker, Context context) { super( boundCenterBottom(defaultMarker) ); setLastFocusedIndex(-1); populate(); this.context = context; this.defaultMarker = defaultMarker; gestureDetector = new GestureDetector(this); } @Override protected OverlayItem createItem(int i) { GeoPoint point = points.get(i); OverlayItem overlayItem = new OverlayItem(point, null, null); overlayItem.setMarker(boundCenterBottom(defaultMarker)); //これをしないとhitTestでNullPointerExceptionが発生します。 return overlayItem; } @Override public int size() { return points.size(); } public void addPin(GeoPoint point, String title, String snippet, int icontype) { if (getIndexGeoPoint(point) == -1) { this.points.add(point); this.icontype.add(icontype); } setLastFocusedIndex(-1); populate(); } // 位置が一致するか(一致しない場合は -1を返す) private int getIndexGeoPoint(GeoPoint newPoint) { int result = -1; int size = this.points.size(); for (int i = 0; i < size; i++) { GeoPoint point = this.points.get(i); if (point.equals(newPoint)) { result = i; break; } } return result; }
private int hitTest(Projection pj, int x, int y){ int hitIndex = -1; String TAG = "hitTest"; Point hitPoint = new Point(x, y); for(int i = 0; i < this.points.size(); i++){ OverlayItem item = getItem(i); Point point = new Point(); pj.toPixels(item.getPoint(), point); int halfWidth = item.getMarker(0).getIntrinsicWidth() / 2; int left = point.x - halfWidth; int right = point.x + halfWidth; int top = point.y - item.getMarker(0).getIntrinsicHeight(); int bottom = point.y; //Log.d(TAG, "left: " + left); //Log.d(TAG, "rihgt: " + right); //Log.d(TAG, "top: " + top); //Log.d(TAG, "bottom: " + bottom); //Log.d(TAG, "hitX: " + hitPoint.x); //Log.d(TAG, "hitY: " + hitPoint.y); if(left <= hitPoint.x && hitPoint.x <= right){ if(top <= hitPoint.y && hitPoint.y <= bottom){ Log.d(TAG, "left: " + left); Log.d(TAG, "rihgt: " + right); Log.d(TAG, "top: " + top); Log.d(TAG, "bottom: " + bottom); Log.d(TAG, "hitX: " + hitPoint.x); Log.d(TAG, "hitY: " + hitPoint.y); hitIndex = i; return i; } } } return hitIndex; } private void onMyTap(int index) { if (points.size() < index) { return; } // ここにタップ時の処理を記述 } public void clearPoint() { this.points.clear(); setLastFocusedIndex(-1); populate(); } @Override public boolean onTouchEvent(MotionEvent e, MapView mapView) { // GestureDetector にタッチイベントを詳細化してもらう gestureDetector.onTouchEvent(e); mMapView = mapView; return super.onTouchEvent(e, mapView); } @Override public boolean onDown(MotionEvent e) { return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { int hitIndex = hitTest(this.mMapView.getProjection(), (int)e.getX(), (int)e.getY()); Log.v("onSingleTapUp", String.valueOf(hitIndex)); if (hitIndex != -1) { onMyTap(hitIndex); } return false; } }
参考にさせていただいたURL
http://d.hatena.ne.jp/sei10sa10/20110802/1312288744
2,824 views