2
votes

onTouch method of my View:

public boolean onTouch(View view, MotionEvent event) {
        Log.d("Touch", "Touch");

        int mNewX = (int) Math.floor(event.getX());
        int mNewY = (int) Math.floor(event.getY());

        boolean isPositionFree = isPositionFree(mNewX, mNewY);

        if (!isPositionFree) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                int i = 0;
                for (Point point : points) { 
                    if (point.spotted) {
                        points.remove(i);
                        invalidate();
                        break;
                    }
                    i++;
                }
            } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
                int i = 0;
                for (Point point : points) { 
                    if (point.spotted) {
                        points.remove(i);
                        Point p = new Point(mNewX, mNewY, point.TYPE);
                        points.add(i, p);
                        invalidate();
                        break;
                    }
                    i++;
                }
            }
        }
}

There are multiple items in the canvas. Their positions are saved in "points". They get drawn to the canvas in a onDraw method via the position of those "points", means Point point.x and point.y.

Now, when I click an item (a point on the canvas), it should disappear. Then, when the MotionEvent.ACTION_MOVE is true, I want to move the point, depending on the event.getX() and event.getY().

the method "isPositionFree(newX,newY)" checks if the point.x and point.y equals newX and newY (the position I just touched on the screen).

if the position is taken (means, there is an item where I just clicked), I'll get to the motionevent-IFs.

Here comes the problem: my code removes the point before I can actually move it. I didnt find any way I could fix this problem for hours. :/ I find it difficult, since the onTouch is always called from the beginning, means ACTION_DOWN and ACTION_MOVE never take place at the same time.

Do you know any fix for this?

thanks in advance, Sebastian

3

3 Answers

3
votes

Got it to work!

For everbody having the same issue, feel free to take this sample code as a help :)

Stuff I declared in the beginning

Vector<Point> points = new Vector<Point>();

Bitmap[] monsterTypes = new Bitmap[3];

Vector<Integer> distanceMovedX = new Vector<Integer>();
Vector<Integer> distanceMovedY = new Vector<Integer>();

int mNewX = -1;
int mNewY = -1;

OnTouch-Method

public boolean onTouch(View view, MotionEvent event) {

        mNewX = (int) FloatMath.floor(event.getX());
        mNewY = (int) FloatMath.floor(event.getY());

        boolean touchedPoint = touchedPoint(mNewX, mNewY);

        switch (event.getAction()) {
        case MotionEvent.ACTION_MOVE:

            distanceMovedX.add(mNewX);
            distanceMovedY.add(mNewY);
            break;
        case MotionEvent.ACTION_UP:

            isMoveEvent = isMoveEvent();
            if (isMoveEvent) {
                for (Point point : points) {

                    if (point.spotted) {

                        // Your code
                    } 
                    i++;
                }
            } else {
                if (touchedPoint) {
                    for (Point point : points) { 
                        if (point.spotted) {

// Your code
                        }
                    }
                }
            }
            distanceMovedX.clear();
            distanceMovedY.clear();
            return true;
        }
        return true;
    }

touchedPoint-Method

public boolean touchedPoint(int mNewX, int mNewY) {
        boolean touchedPoint = false;
        int height = 0;
        int width = 0;

        for (Point point : points) {
            height = monsterTypes[point.TYPE - 1].getHeight();
            width = monsterTypes[point.TYPE - 1].getWidth();

            if (point.x + width < mNewX || point.x > mNewX + width
                    || point.y + height < mNewY || point.y > mNewY + height) {
                touchedPoint = false;
                point.spotted = false;
            } else {
                touchedPoint = true;
                point.spotted = true;
                return touchedPoint;
            }
        }
        return touchedPoint;
    }

isMoveEvent-Method

public boolean isMoveEvent() {
        boolean isMoveEvent = false;
        boolean isMoveEventX = false;
        boolean isMoveEventY = false;

        for (int i = 0; i <= (points.size() -1); i++) {
            Log.d("point", "for loop entered");

            if (!distanceMovedY.isEmpty()) {
                Log.d("point.x", "distanceMovedY is not empty");
                int dMY = distanceMovedY.get(distanceMovedY.size() - 1) - distanceMovedY.get(0);

                if ((dMY > 50 || dMY <= 0) && dMY != 0) {
                    Log.d("point.y", "is move event");
                    Log.d("point.y", "dMY: " + dMY);
                    isMoveEventY = true;
                } else {
                    Log.d("point.x", "is no move event");
                    Log.d("point.x", "dMY: " + dMY);
                    isMoveEvent = false;
                    return isMoveEvent;
                }
            }
            if (!distanceMovedX.isEmpty()) {
                Log.d("point.x", "distanceMovedX is not empty");
                int dMX = distanceMovedX.get(distanceMovedX.size() - 1) - distanceMovedX.get(0);

                if (dMX <= 50 && dMX >= -50 && dMX != 0) {
                    Log.d("point.x", "is move event");
                    Log.d("point.x", "dMX: " + dMX);
                    isMoveEventX = true;
                } else {
                    Log.d("point.x", "is no move event");
                    Log.d("point.x", "dMX: " + dMX);
                    isMoveEvent = false;
                    return isMoveEvent;
                }
            }
            if (isMoveEventX && isMoveEventY) {
                Log.d("point", "is move event");
                isMoveEvent = true;
                return isMoveEvent;
            }
        }
        Log.d("point", "is no move event");
        return isMoveEvent;
    }

Point Class

class Point { int x, y; int TYPE; boolean spotted; boolean halfSpotted;

public Point() {
}

public Point(int x, int y, int t) {
    this.x = x;
    this.y = y;
    this.TYPE = t;
}

@Override
public String toString() {
    return x + ", " + y;
}

}

EXPLANATION:

Point: we got a class Point. All those points declared in the Vector are x- and y-coordinates on your canvas. They help us to check the position we clicked.

monsterTypes: its the different graphics I use. If you only use one graphic that you draw onto the canvas, change it to your needs

distanceMovedX & Y: saves all the X and Y Coordinates of your "ACTION_MOVE". From pos 0 (the first touched point) to pos Z (the last touched point, where ACTION_UP occurs). Though its not the original X and Y position. Its the result of posZ - pos0. With these values you can determine, after what distance travelled you wanna invoke "onMove" and BELOW which distance "onClick" should be invoked.

mNewX & Y: the currently position of your onTouch-Method. Everytime you move your finger, newX & Y become overwritten.

Methods:

onTouch(): First, we'll overwrite mNewX and Y to the current position touched. Then we check if we clicked on an existing spot (in my case some 48px*48px area) Next we record the taken distance in ACTION_MOVE. After that we continue with ACTION_UP, where we check if we just performed some moveEvent or clickEvent.

touchedPoint(): calculates if we touched some existing point on the canvas, or not. returns true or false

isMoveEvent(): checks if we moved the certain distance. in my case i wanna move down, 50px or more. though im not allowed to move sidewards -50px or +50px. If its NOT a move event, the last spot touched still has to be on the in the giving distance (in my case in the 48px*48px range of the point).

Thats it. took me days to only figure out that option ;/ ashamed of that ... though I coded it pretty fast, what makes me feeling better again :D

0
votes

I'm just suggesting some walk-around :

Instead of removing the point when clicking it, make a privata Point in your class, where you currently remove the point, just set your new Variable Point to the Point you would remove...

Then, after using it in action or action move, the last place you would use it, check if your private variable is not null, if so, remove it, then, set it to null.

-1
votes

try using a switch case statement:

switch finger_action:

case(ACTION_MOVE)
{
//move code
return false;
}
case(ACTION_TOUCH)
{
//dissappear code
return false;
}

note the up above code is pseudo code, but what it does it checks to see if you are moving the dot before just touching it. this way the dot will attempt a move first instead of being removed first.

thanks, Alex