0

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!

4

1 回答 1

1

我在 DotView 类中添加了触摸监听器,以便它可以拥有自己的“触摸反馈”。活动中还有另一个触摸侦听器,我试图用它来获取绘制线所需的点。据我所知,触摸监听器工作正常 - 它们不会相互干扰。

我不太明白为什么你需要两个触摸监听器。要画线,触摸监听器TableLayout应该绰绰有余。

您的代码的问题(或至少从我所见)是您使用该getLocationOnScreen(coordsArray)方法而不将返回的值转换回LineView. 例如,您得到 a 的坐标,DotView即 x 和 y。然后,您在LineView. 但是,LineView它何时绘制将使用其自己的(标准)坐标系,该坐标系将视图的左上角置于 (0,0) 并且坐标将不匹配。这是一个示例:假设您触摸DotView高度为 50 的第一个,并且该getLocationOnScreen()方法返回的 y 为 100。您计算出最高点的中心DotView将位于 125(100 + 50 / 2)。在LineView将偏离正常位置,因为实际绘图将在 125 处完成,在屏幕坐标中将在视觉上转换为 225 中的任何一个(getLocationOnScreen()+ 125 返回 100)。

无论如何,我已经使用该getLocationOnScreen()方法做了一个小例子来做你想做的事情(你可以在这里找到)。

于 2013-10-29T10:39:59.940 回答