简体   繁体   English

如何使用OnTouchListener获取对象的正确坐标(event.getX()/ event.getY())

[英]How to get correct coords(event.getX() / event.getY()) of Object with OnTouchListener

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). 我确切想要的是通过OnTouchListener(中心带有点的橙色正方形 )通过对象的坐标 (X,Y)显示位图的一部分。

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)) ? PS:据我了解, event.getX() / event.getY()正在获得相对坐标(对我来说还不清楚,从带有触摸监听器的图像视图对象中获得的确切坐标是什么(中心带有点的橙色正方形),我的意思是获取此对象的中心Top.Left corners(X,Y))?

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() . 使用event.getX()而不是view.getX() the view.getX() returns position of the view you are touching not the touch event you are interested in. view.getX()返回您正在触摸的视图的位置,而不是您感兴趣的触摸事件。

This is the Y coordinate which will likely be inverted. 这是可能会反转的Y坐标。

so event.getX() is the position of the touch event. 因此event.getX()是触摸事件的位置。

event.getY() is the inverted Y position so getHeight() - event.getY() will give you the Y position you are after. event.getY()是反向的Y位置,因此getHeight() - event.getY()会为您提供您所追求的Y位置。

EDIT 编辑

In the case of MOTION_MOVE getX and getY return the most recent and maintains historical data. 对于MOTION_MOVE,getX和getY返回最新的数据并维护历史数据。 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 批处理-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. 为了提高效率,带有ACTION_MOVE的运动事件可以将单个对象内的多个运动样本批处理在一起。 The most current pointer coordinates are available using getX(int) and getY(int). 使用getX(int)和getY(int)可获得最新的指针坐标。 Earlier coordinates within the batch are accessed using getHistoricalX(int, int) and getHistoricalY(int, int). 使用getHistoricalX(int,int)和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. 要按时间顺序处理批处理中的所有坐标,请首先使用历史坐标,然后使用当前坐标。

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();

So it was simple to resolve this problem. 因此,解决此问题很简单。
Solution : 解决方案
I have an object( orange square ) with OnTouchListener(for eg he's an quad with size 50dp Height / 50dp Width ). 我有一个带有OnTouchListener的对象( 橙色正方形 )(例如,他是一个大小为50dp Height / 50dp Width的四边形)。
So view.getX()/view.getY() takes relative coords(center) of object(that have OnTouchListener). 因此, view.getX()/ view.getY()采用具有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! 请享用!

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. 在某些硬件上的Android Pie上仍然会发生这种情况。 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. 解决奇数触摸事件的唯一方法是,如果在ACTION_MOVE期间没有奇异动作,则比较最后3个事件,然后再放置视图位置。 Below is a sample when checking the event on a circular view. 以下是在圆形视图上检查事件的示例。 Assumption is that you created a new double[3] temporary variable : 假设您创建了一个新的double [3]临时变量:

  /**
     * 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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM