How to get correct coords(event.getX() / event.get

2020-02-07 13:03发布

问题:

I have this :

and what i want exactly is that to show portion of Bitmap via coords(X,Y) of object with OnTouchListener(orange square with dot in center).

So the problem is that i want to draw portion of image like it shows on image(Red square "Area that i want" to show).
So in this case,excepted result is(portion of bitmap) :

At current moment i'm doing like this:

public boolean onTouch(View view, MotionEvent event) {

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

            Bitmap mBitmap = Bitmap.createBitmap(sourceBitmap,view.getX() - view.getWidth(),view.getY()-view.getHeight(),250,250);
            //other stuff to fill this portion of bitmap
            break;
    }

    return true;
}
}

And it's not correct.

how can i achieve this? Tried a lot of formulas,but no luck. Any suggestions?

PS As i understand event.getX()/event.getY() is getting relative coords(and it's not clear for me,what exactly coords getting from object of imageview with touch listener(orange square with dot in center),i mean its getting center of this objects or Top.Left corners(X,Y)) ?

回答1:

Sorry, whilst looking in more detail coming up with solution i think i found it and I am at work so can you try this:

Use event.getX() not view.getX(). the view.getX() returns position of the view you are touching not the touch event you are interested in.

This is the Y coordinate which will likely be inverted.

so event.getX() is the position of the touch event.

event.getY() is the inverted Y position so getHeight() - event.getY() will give you the Y position you are after.

EDIT

In the case of MOTION_MOVE getX and getY return the most recent and maintains historical data. i guess the most recent one is the most valuable as that's where you will be drawing.

In that case use batching quote from documentation:

Batching - http://developer.android.com/reference/android/view/MotionEvent.html

For efficiency, motion events with ACTION_MOVE may batch together multiple movement samples within a single object. The most current pointer coordinates are available using getX(int) and getY(int). Earlier coordinates within the batch are accessed using getHistoricalX(int, int) and getHistoricalY(int, int). The coordinates are "historical" only insofar as they are older than the current coordinates in the batch; however, they are still distinct from any other coordinates reported in prior motion events. To process all coordinates in the batch in time order, first consume the historical coordinates then consume the current coordinates.



回答2:

You have to get the coordinates like this , it will give you coordinates with reference to view not the screen.

                float xCord = event.getRawX()-v.getX();
                float yCord = event.getRawY()-v.getY();


回答3:

So it was simple to resolve this problem.
Solution:
I have an object(orange square) with OnTouchListener(for e.g. he's an quad with size 50dp Height/ 50dp Width).
So view.getX()/view.getY() takes relative coords(center) of object(that have OnTouchListener).
So what i needed:

//imageview parameters ,where i will show this part of bitmap
int Width = img.getWidth();
int Height = img.getHeight();
//after this,i make margin of my coords,via this simple formula -> Current Coord X - Width / 2 (same for Y)
 Bitmap mBitmap = Bitmap.createBitmap(sourceBitmap,view.getX() - Width / 2,view.getY()-Height / 2,Width,Height);  

And that is all.
Enjoy!



回答4:

Sadly there's no easy way of solving this if you want to really address the event within the bounds of the view. This is still occurring on Android Pie on some hardware. The only way to address odd touch events is to compare the last 3 events if there are no odd movements during ACTION_MOVE before rending the position of the view. Below is a sample when checking the event on a circular view. Assumption is that you created a new double[3] temporary variable :

  /**
     * This detects if your finger movement is a result of an actual raw touch event of if it's from a view jitter.
     * This uses 3 events of rotation as temporary storage so that differentiation between swapping touch events can be determined.
     *
     * @param newRotationValue
     */
    private boolean isRotationTouchEventConsistent(final double newRotationValue) {
        double evalValue = newRotationValue;

        if (Double.compare(newRotationStore[2], newRotationStore[1]) != 0) {
            newRotationStore[2] = newRotationStore[1];
        }
        if (Double.compare(newRotationStore[1], newRotationStore[0]) != 0) {
            newRotationStore[1] = newRotationStore[0];
        }

        newRotationStore[0] = evalValue;

        if (Double.compare(newRotationStore[2], newRotationStore[0]) == 0
                || Double.compare(newRotationStore[1], newRotationStore[0]) == 0
                || Double.compare(newRotationStore[2], newRotationStore[1]) == 0

                //Is the middle event the odd one out
                || (newRotationStore[0] > newRotationStore[1] && newRotationStore[1] < newRotationStore[2])
                || (newRotationStore[0] < newRotationStore[1] && newRotationStore[1] > newRotationStore[2])
        ) {
            return false;
        }
        return true;
    }