Piotr Chojnacki
Piotr Chojnacki

Reputation: 6867

Redraw view during MotionEvent.ACTION_MOVE in onTouchEvent()

I have created my own component which extends RelativeLayout, inside it I have a field of View type which is being positioned with margins:

enter image description here

Blue quad represents my parent view, and a red circle is a child.

Now I want to allow user to move this red circle while moving a finger on a screen. This is my onTouchEvent() method:

@Override
public boolean onTouchEvent(MotionEvent event) {

    int eventAction = event.getAction();

    switch (eventAction) {
        case MotionEvent.ACTION_DOWN: 
            // finger touches the screen
            break;

        case MotionEvent.ACTION_MOVE:
                marginX = (int)event.getX();
                marginY = (int)event.getY();
                RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams(); // pointer is this red circle
                lp.setMargins(marginX, marginY, 0, 0);

            break;

        case MotionEvent.ACTION_UP:   
            // finger leaves the screen
            break;
    }


    return true;
}

But I quickly found out that it doesn't refresh it's position while user is moving his finger on a screen, but instead it does it only when user releases his finger from the screen. So basically, when I move my finger, circle stays in a same position, but when I stop moving, circle is drawn in new position. I tried using invalidate() method on both, parent and child views, but it didn't help. I assume that it may have something to do with UI thread, but I don't have access to runOnUiThread()' method as it's not anActivity`.

EDIT: I passed an activity to my class, so that I can use runOnUiThread(). My case: ACTION_MOVE now looks like this:

case MotionEvent.ACTION_MOVE:      
    marginX = (int)event.getX();
    marginY = (int)event.getY();

    activity.runOnUiThread(new Runnable() {
        public void run() { 
        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)pointer.getLayoutParams();
        lp.setMargins(marginX, marginY, 0, 0);
        pointer.invalidate();
        }
    });

break;

Upvotes: 4

Views: 2207

Answers (2)

dziwna
dziwna

Reputation: 1242

If it's simple pointer you can draw it on Canvas as Drawable:

@Override
protected void onDraw(Canvas canvas) {
    pointer.setBounds(marginX, marginY, marginX + pointerWidth, marginY + pointerHeight);
    pointer.draw(canvas);

    super.onDraw(canvas);
}

And then call invalidate() on pointer in onTouchEvent() method.

Upvotes: 2

Rakesh L
Rakesh L

Reputation: 132

I think you need drag and drop function

Refer http://www.vogella.com/articles/AndroidDragAndDrop/article.html

Upvotes: 2

Related Questions