Search code examples
androidandroid-mapviewhittesttouch-eventosmdroid

Unable to implement onTouchEvent (Drag & Drop) with Osmdroid


I had been trying to implement OnTouchEvent so I can react when an user move (drag & drop) an overlayitem.

I found something similar on the Osmdroid site: http://code.google.com/p/osmdroid/issues/detail?id=225. I am using the code there as reference but still is not working for me and then my application is crashing when it get to the hitTest.

Any suggestion? Thanks.

public boolean onTouchEvent(MotionEvent event, MapView mapView) {

    final int action = event.getAction();
    final int x = (int) event.getX();
    final int y = (int) event.getY();

    final Projection pj = mapView.getProjection();

    boolean result = false;
    //Object TAG;
    //Log.d(TAG, "onTouchEvent entered");

    System.out.println("onTouchEvent!");        
    Point p = new Point(0,0);
    Point t = new Point(0,0);

    //System.out.print(MotionEvent.ACTION_DOWN);
    //System.out.print(action);

    if (action == MotionEvent.ACTION_DOWN) {

        System.out.println("Action Down!");

        for (OverlayItem item : mOverlays) {

            // Create a new GeoPoint from pixel coordinates (x, y, pointReuse):
            //pj.fromMapPixels(x, y, t);

            // Convert the given GeoPoint to onscreen pixel coordinates (GeoPoint, pointOut):
            pj.toPixels(item.getPoint(), p);

            //System.out.println(t.x);
            //System.out.println(p.x);

            //System.out.println(t.y);
            //System.out.println(p.y);

            defaultMarker = item.getDrawable();

            if (hitTest(item, defaultMarker, x - p.x, y - p.y)) {
                System.out.println("Action Down -> IF!");
                result = true;
                inDrag = item;
                mOverlays.remove(inDrag);
                populate();

                xDragTouchOffset = 0;
                yDragTouchOffset = 0;

                setDragImagePosition(x, y);
                dragImage.setVisibility(View.VISIBLE);

                xDragTouchOffset = t.x - p.x;
                yDragTouchOffset = t.y - p.y;

                break;
            }
        }

    } 

    else if (action == MotionEvent.ACTION_MOVE && inDrag != null) {
        //dragImage.setVisibility(View.VISIBLE);
        setDragImagePosition(x, y);
        System.out.println("Action Move!");
        result = true;
    } 

    else if (action == MotionEvent.ACTION_UP && inDrag != null) {
        dragImage.setVisibility(View.GONE);

        GeoPoint pt = (GeoPoint) pj.fromPixels(x - xDragTouchOffset, y - yDragTouchOffset);
        OverlayItem toDrop = new OverlayItem(inDrag.getTitle(),
                inDrag.getSnippet(), pt);

        mOverlays.add(toDrop);
        populate();

        inDrag = null;
        result = true; 

        pj.fromMapPixels(x, y, t);

        if((t.x - p.x) == xDragTouchOffset && (t.y - p.y) == yDragTouchOffset) {
            System.out.println ("Do something here if desired because we didn't move item " + toDrop.getTitle() );
        }

        System.out.println("Action Up!");

    }
    System.out.print(inDrag);
    return (result || super.onTouchEvent(event, mapView));
}

private void setDragImagePosition(int x, int y) {
    RelativeLayout.LayoutParams lp=
            (RelativeLayout.LayoutParams)dragImage.getLayoutParams();
    lp.setMargins(x-xDragImageOffset-xDragTouchOffset,
            y-yDragImageOffset-yDragTouchOffset, 0, 0);
    dragImage.setLayoutParams(lp);
    }

Solution

  • I got the above code working. I only noticed two things different between my working code and yours. One is the hitTest paramaters you are sending, try changing

    if (hitTest(item, defaultMarker, x - p.x, y - p.y)) {

    to

    if (hitTest(item, defaultMarker, t.x - p.x, t.y - p.y)) {

    The second is that you should uncomment pj.fromMapPixels(x, y, t);

    also you should probably uncomment dragImage.setVisibility(View.VISIBLE); if you want to see the image as you are dragging it