Search code examples
javaandroidmotionevent

Movement of simultaneous two bitmap on a view with MotionEvent


I created two bitmap on my view using the following class (Simple 2D Graphics in android) and wandering to achieve that bitmap can move independently. I am calling motionevent method for this.

Current issue, i do not understand why does only one object is moving right in the following code. e.g. with this code, only "not" bitmap is moved, i would like to move both bitmaps independently of eachother.

scenrio: i can use my two fingures, one for each object, to move the bitmaps independently. but i don't know how to achieve this.

public class TouchView extends View {

private Drawable cross;
private Rect crossBounds = null;
private Drawable not;
private Rect notBounds = null;

private int x1, y1, x2, y2 ;

boolean flag = true;

private void intialize ()
{ 
    int w1 = cross.getIntrinsicWidth();
    int h1 = cross.getIntrinsicHeight();
     x1 = 100;
    y1 = 100;
    crossBounds = new Rect(x1-w1/2, y1-w1/2, x1+w1/2, y1+h1/2);

    int w = not.getIntrinsicWidth();
    int h = not.getIntrinsicHeight();
     x2 = 300;
    y2 = 300;
    notBounds = new Rect(x2-w/2, y2-w/2, x2+w/2, y2+h/2);

}

public TouchView(Context context) {
    super(context);

    // Get a representation of the image
    Resources resources = context.getResources();
    cross = (Drawable) resources.getDrawable(R.drawable.cross);
    not = (Drawable) resources.getDrawable(R.drawable.not);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.i("TouchView.onTouchEvent", "event = " + event);

    if(event.getAction() == MotionEvent.ACTION_DOWN || 
            event.getAction() == MotionEvent.ACTION_MOVE) {

        int touchCounter = event.getPointerCount();


         if (touchCounter ==2 && getHeight ()==y1){
                int w = cross.getIntrinsicWidth();
                int h = cross.getIntrinsicHeight();
                 x1 = (int) event.getX();

                crossBounds = new Rect(x1-w/2, y1-w/2, x1+w/2, y1+h/2);
                }
                else
                {
                int w1 = not.getIntrinsicWidth();
                int h1 = not.getIntrinsicHeight();
                 x2 = (int) event.getX();

                notBounds = new Rect(x2-w1/2, y2-w1/2, x2+w1/2, y2+h1/2);
                }
                // Request the system to redraw the view (call onDraw at 
                // some point in the future)
                // From a non-UI thread, call postInvalidate instead





        invalidate();

        return true;
    }

    return false;
}



@Override
protected void onDraw(Canvas canvas) {

    Log.i("TouchView.onDraw", "");

    // Background
    Paint bgPaint = new Paint();
    bgPaint.setColor(Color.WHITE);
    canvas.drawPaint(bgPaint);

    if (flag == true){
        intialize ();
        cross.setBounds(crossBounds);
        cross.draw(canvas);
        not.setBounds(notBounds);
        not.draw(canvas);
        flag=false;
    }
    if(crossBounds != null) {
        cross.setBounds(crossBounds);
        cross.draw(canvas);
        not.setBounds(notBounds);
        not.draw(canvas);
    }
}
}

Solution

  • public class SimpleDrag extends View {
    
    
    
    private final int INVALID_INDEX = -1;
    
    private final int mTotalItems = 5;
    
    private ArrayList<Rect> mItemsCollection;
    
    private ArrayList<Point> mActiveDragPoints;
    
    private ArrayList<Rect>  mActiveRects;
    
    
    private Paint mPaint;
    
    /**
     * @param context  
     * @return of type SimpleDrag
     * Constructor function
     * @since Feb 19, 2013 
     * @author rajeshcp
     */
    public SimpleDrag(Context context) {
        super(context);
        init();
    }
    
    /**
     * @param context
     * @param attrs  
     * @return of type SimpleDrag
     * Constructor function
     * @since Feb 19, 2013 
     * @author rajeshcp
     */
    public SimpleDrag(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    
    /**
     * @param context
     * @param attrs
     * @param defStyle  
     * @return of type SimpleDrag
     * Constructor function
     * @since Feb 19, 2013 
     * @author rajeshcp
     */
    public SimpleDrag(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
    
    /* (non-Javadoc)
     * @see android.view.View#onDraw(android.graphics.Canvas)
     * @since Feb 19, 2013
     * @author rajeshcp 
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLUE, PorterDuff.Mode.CLEAR);
        for( Rect rect : mItemsCollection)
        {
            canvas.drawRect(rect, mPaint);
        }
    }
    
    
    /**
     * @param of type null
     * @return of type null
     * function which will initialize the view
     * @since Feb 20, 2013
     * @author rajeshcp
     */
    private void init()
    {
        mActiveRects      = new ArrayList<Rect>(mTotalItems);
        mActiveDragPoints = new ArrayList<Point>(mTotalItems);
        mItemsCollection  = new ArrayList<Rect>();
        for( int i = 0; i < mTotalItems; i++)
        {
            Rect rect = new Rect(i * 100, i * 100, (i + 1) * 100, (i + 1) * 100);
            mItemsCollection.add(rect);
        }
        mPaint     = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
    }
    
    
    
    
    
    /* (non-Javadoc)
     * @see android.view.View#onTouchEvent(android.view.MotionEvent)
     * @since Feb 19, 2013
     * @author rajeshcp 
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
    
        final int action  = event.getActionMasked();
        final int pointer = event.getActionIndex();
    
        switch (action) {
        case MotionEvent.ACTION_DOWN :
            Point touchDown = new Point((int)event.getX(), (int)event.getY());
            lookForIntersection(touchDown);
            break;
        case MotionEvent.ACTION_UP :
        case MotionEvent.ACTION_CANCEL :
            mActiveDragPoints.removeAll(mActiveDragPoints);
            mActiveRects.removeAll(mActiveRects);
            break;
        case MotionEvent.ACTION_MOVE :
            int count = 0;
            for(Rect rect : mActiveRects)
            {
                Point curretPoint = new Point((int)event.getX(count), (int)event.getY(count));
                moveRect(curretPoint, mActiveDragPoints.get(count), rect);
                count++;
            }
            Log.d(getClass().getName(), "Active Rects" + mActiveRects.size());
            Log.d(getClass().getName(), "Active Points" + mActiveDragPoints.size());
            invalidate();
            break;
        case MotionEvent.ACTION_POINTER_DOWN :
            touchDown = new Point((int)event.getX(pointer), (int)event.getY(pointer));
            lookForIntersection(touchDown);
            //Log.d(getClass().getName(), "ACTION_POINTER_DOWN" + pointer);
            break;
        case MotionEvent.ACTION_POINTER_UP :
            int index = getIntersectionRectIndex(new Point((int)event.getX(pointer), (int)event.getY(pointer)));
            if( index != INVALID_INDEX )
            {
                Rect rect = mItemsCollection.get(index);
                mActiveDragPoints.remove(mActiveRects.indexOf(rect));
                mActiveRects.remove(rect);
            }
    
            break;
    
        default:
            break;
        }
        return true;
    }
    
    
    /**
     * @param touchDown of type Point
     * @return of type null
     * function which will find the 
     * intersecting rect and add to the 
     * active collection
     * @since Feb 20, 2013
     * @author rajeshcp
     */
    private void lookForIntersection(Point touchDown)
    {
        final int index = getIntersectionRectIndex(touchDown);
    
        if( index != INVALID_INDEX )
        {
            final Rect rect = mItemsCollection.get(index);
            if( mActiveRects.indexOf(rect) == INVALID_INDEX )
            {
                mActiveDragPoints.add(touchDown);
                mActiveRects.add(mItemsCollection.get(index));
            }
        }
        Log.d(getClass().getName(), "Active Rects" + mActiveRects.size());
        Log.d(getClass().getName(), "Active Points" + mActiveDragPoints.size());
    
    }
    
    
    
    
    /**
     * @param point of type Point
     * @return of type int 
     * function which will return the index of 
     * the rect contaning the given point
     * @since Feb 20, 2013
     * @author rajeshcp
     */
    private int getIntersectionRectIndex(final Point point)
    {
        int index = INVALID_INDEX;
        for(Rect rect : mItemsCollection)
        {
            if( rect.contains(point.x, point.y) )
            {
                index = mItemsCollection.indexOf(rect);
                break;
            }
        }
        return index;
    }
    
    
    /**
     * @param currentPoint of type Point
     * @param prevPoint of type Point 
     * @param rect of type Rect
     * @return of type null
     * function which will move the change the 
     * bounds of teh rect
     * @since Feb 20, 2013
     * @author rajeshcp
     */
    private void moveRect(Point currentPoint, Point prevPoint, final Rect rect)
    {
        int xMoved = currentPoint.x - prevPoint.x;
        int yMoved = currentPoint.y - prevPoint.y;
        rect.set(rect.left + xMoved, rect.top + yMoved, rect.right + xMoved, rect.bottom + yMoved);
        mActiveDragPoints.set(mActiveDragPoints.indexOf(prevPoint), currentPoint);
    }
    
    }
    

    Hope this is what you want, haven't tested a lot, but basically this is working for me even you can increase the nof items by changing the mTotalItems. Hope this will help.