在手指运动event.getX()和getY()之后画一条线是不正确的 UPDATE[英] Drawing a line following finger - motionevent.getX() and getY() incorrect UPDATE

本文是小编为大家收集整理的关于在手指运动event.getX()和getY()之后画一条线是不正确的 UPDATE的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

更新:请再次阅读整个问题: - )

背景:

我通过创建自定义视图并将这些视图添加到TableLayout,创建了一个圆点网格.目的是让我能够以一种方式将一条线从其中一个点绘制到另一个点,使得当按下点时,从按压点的中心开始到手指当前的点接触.当手指拖到另一个点上时,该线在该点的中心完成.结果是从压制点的中心绘制到由手指拖过的点的中心.

要创建越过TableLayout的行,我创建了一个新的自定义视图,刚刚在具有canvas.drawLine()方法之间的点之间创建了一行.然后,我创建了一个FrameLayout,其中我把tablelayout和lineview放在那里.这意味着线视图将能够在Tablelayout之上绘制.

当前情况:

我在dotview类中添加了触摸侦听器,以便它可以有自己的"触摸反馈".在活动中还有另一个触摸侦听器,我试图用来获得绘制行所需的积分.触摸侦听器据我所知,他们的工作正常 - 他们并不是互相干扰.

问题正在绘制正确的坐标.我尝试了许多方法来获得被按下的点中心的坐标(线路的起点),但我仍然没有管理它.这个问题有更多信息:获得aveive的中心的坐标.第二部分是得到正确的终点.出于这个问题的目的,我会喜欢线的结尾来遵循手指的位置.我认为它和motionevent.getX() / getY()一样简单,但这没有工作.所发生的情况是,相对于点和坐标相对于整个布局/屏幕,坐标之间的坐标与坐标之间有混合.

简单地放置:getx()和gety()值不正确,这就是我在这里解决的问题.

如屏幕截图所示,当我按下点上时,线的起点大致位于正确的位置,但终点是关闭.我无法真正解释原因.

我已经尝试过getRawX()和getRawY(),它们返回更准确的值,但它们仍然不正确,填充量(或类似的东西 - 我没有100%理解).

这会显示我的代码

在我的Activity:

    LineView test;
    FrameLayout fl;
     float startPointX = 0;
    float startPointY = 0;

    // Removed 

    @Override
    public boolean onTouch(View view, MotionEvent event) {

        float eventX = event.getX();
        float eventY = event.getY();

        int[] loc = new int[2];

        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            if (view instanceof DotView) {

                DotView touchedDv = (DotView) view;

                int dotColor = touchedDv.getColor();
                test.setColor(dotColor);

                float[] f = touchedDv.getDotCenterLocationOnScreen();
                startPointX = f[0];
                startPointY = f[1];

                test.setPoints(startPointX, startPointY, eventX, eventY);
fl.addView(test);
            }

            vib.vibrate(35);


            return false; 
        case MotionEvent.ACTION_MOVE:

            test.setPoints(startPointX, startPointY, eventX, eventY);

            break;
        case MotionEvent.ACTION_UP:

            fl.removeView(test);

            return false;

        default:
            return false;
        }

        return true;
    }

最后LineView:

public class LineView extends View {

public static final int LINE_WIDTH = 10;
Paint paint = new Paint();

float startingX, startingY, endingX, endingY;

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

    paint.setColor(Color.MAGENTA);
    paint.setStrokeWidth(LINE_WIDTH);

}

public void setPoints(float startX, float startY, float endX, float endY) {

    startingX = startX;
    startingY = startY;
    endingX = endX;
    endingY = endY;
            invalidate();
}


@Override
public void onDraw(Canvas canvas) {

    canvas.drawLine(startingX, startingY, endingX, endingY, paint);

}

注意:

  • 我呼叫左上角"dot 1".

  • 屏幕截图可能并不完全准确,因为我的手指移动 当我拍摄屏幕截图时,但我描述的行为是 发生.

screenshot 1

屏幕截图2

如果需要任何其他信息/代码,我会愉快地提供它.

谢谢你花时间读到这一点 - 对不起,这太长了!

推荐答案

我在dotview类中添加了触摸侦听器,以便它可以拥有 它自己的"触摸反馈".还有另一个触摸侦听器 我想用来获得吸引所需的积分的活动 线.触摸听众据我所知 不互相干扰.

我不太了解为什么你需要两个触摸侦听器.要在TableLayout上绘制触摸侦听器应绰绰有余.

您的代码(或者至少来自我所见的问题)是您使用getLocationOnScreen(coordsArray)方法,而不将返回的值转换回LineView的坐标系统.例如,您可以获得DotView的坐标,这将是x和y.然后,您将在LineView中使用此值.但是,LineView当它将其图纸将使用它自己的(标准)坐标系统,该系统将视图的左上角置于(0,0),并且坐标不会匹配.以下是一个例子:假设您触摸具有50的高度的第50次,并且由getLocationOnScreen()方法返回的Y为100.计算C13> WICH的中心将在125(100 + 50/2).在LineView中使用该值将是从正常位置的方式关闭,因为实际绘图将在125处完成,在屏幕坐标中将视觉平移到225的AY(100由getLocationOnScreen() + 125返回).

无论如何我使用了getLocationOnScreen()方法做了一个小的例子来做你想要做的事情(你可以找到 here ).

本文地址:https://www.itbaoku.cn/post/102781.html

问题描述

UPDATE: please read entire question again :-)

Background:

I have created a grid of dots by creating a custom view and then adding these views to a TableLayout. The aim is for me to be able to draw a line from one of these dots to another dot in a way so that when a dot is pressed, a line is started from the center of the pressed dot to the point where the finger is currently touching. When the finger is dragged over another dot, the line then finishes at the center of that dot. The result being a line drawn from the center of the pressed dot to the center of the dot which was dragged over by the finger.

To create a line going over the TableLayout, I created a new custom view which just created a line between points with the canvas.drawLine() method. I then created a FrameLayout in which I put the TableLayout and the LineView. This meant the line view would be able to be drawn on top of the TableLayout.

Current Situation:

I have added touch listener in the DotView class so that it can have its own “touch feedback”. There is also another touch listener in the activity which I am trying to use to get the points needed to draw the line. The touch listeners are working fine as far as I can tell - they are not interfering with each other.

The problem is getting the correct coordinates to plot the line. I have tried a number of ways to get the coordinates of the center of the dot that was pressed (the starting point of the line), but I still have not managed it. This question, has more information: Get the coordinates of the center of a view . The second part is getting the correct end point of the line. For the purposes of this question, I would just like the end of the line to follow the position of the finger. I thought it was as easy as motionevent.getX() / getY() but this hasn’t worked. What happened instead was that there was a mix up between the coordinates on a scale relative to the layout of the dot and the coordinates relative to the whole layout/screen.

Simply put: the getX() and getY() values are incorrect, and this is what I am trying to solve here.

As shown in the screenshots, when I press down on a dot, the start point of the line is roughly in the right place, but the end point is way off. I can’t really explain why.

I have tried getRawX() and getRawY() and they return more much more accurate values, but they are still incorrect by the amount of padding (or something like that - I don’t 100% understand).

This shows my code

In my Activity :

    LineView test;
    FrameLayout fl;
     float startPointX = 0;
    float startPointY = 0;

    // Removed 

    @Override
    public boolean onTouch(View view, MotionEvent event) {

        float eventX = event.getX();
        float eventY = event.getY();

        int[] loc = new int[2];

        switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            if (view instanceof DotView) {

                DotView touchedDv = (DotView) view;

                int dotColor = touchedDv.getColor();
                test.setColor(dotColor);

                float[] f = touchedDv.getDotCenterLocationOnScreen();
                startPointX = f[0];
                startPointY = f[1];

                test.setPoints(startPointX, startPointY, eventX, eventY);
fl.addView(test);
            }

            vib.vibrate(35);


            return false; 
        case MotionEvent.ACTION_MOVE:

            test.setPoints(startPointX, startPointY, eventX, eventY);

            break;
        case MotionEvent.ACTION_UP:

            fl.removeView(test);

            return false;

        default:
            return false;
        }

        return true;
    }

And finally the LineView:

public class LineView extends View {

public static final int LINE_WIDTH = 10;
Paint paint = new Paint();

float startingX, startingY, endingX, endingY;

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

    paint.setColor(Color.MAGENTA);
    paint.setStrokeWidth(LINE_WIDTH);

}

public void setPoints(float startX, float startY, float endX, float endY) {

    startingX = startX;
    startingY = startY;
    endingX = endX;
    endingY = endY;
            invalidate();
}


@Override
public void onDraw(Canvas canvas) {

    canvas.drawLine(startingX, startingY, endingX, endingY, paint);

}

NOTES:

  • I am calling the top left hand dot "dot 1".

  • The screenshots may not be entirely accurate as my finger moves slightly when I take the screenshot, but the behaviour I described is happening.

Screenshot 1

Screenshot 2

If any other information/code is wanted, I will happily provide it.

Thanks for taking the time to read this - sorry it is so long!

推荐答案

I have added touch listener in the DotView class so that it can have its own “touch feedback”. There is also another touch listener in the activity which I am trying to use to get the points needed to draw the line. The touch listeners are working fine as far as I can tell - they are not interfering with each other.

I don't quite see why you need both touch listener. To draw the line the touch listener on the TableLayout should be more than enough.

The problem with your code(or at least from what I've seen) is that you use the getLocationOnScreen(coordsArray) method without translating the returned values back to the coordinates system of the LineView. For example, you get the coordinates of a DotView which will be x and y. You then use this values in the LineView. But, the LineView when it will do its drawings will use its own(standard) coordinates system which places the top-left of the view at (0,0) and the coordinates will not match. Here's an example: suppose you touch the very first DotView which has a height of 50 and the y returned by the getLocationOnScreen() method is 100. You calculate the center of the DotView wich will come be at 125(100 + 50 / 2). Using this value in the LineView will be way off the normal position as the actual drawing will be done at 125, which in screen coordinates will visually translate to a y of 225 (100 returned by getLocationOnScreen() + 125).

Anyway I've made a small example using the getLocationOnScreen() method to do what you're trying to do(which you can find here).