カテゴリー
SugiBlog Webエンジニアのためのお役立ちTips

GoogleMapのアイコンタップ

この記事は最終更新日から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,835 views

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です