在finger-motionevent.getX()和getY()之后绘制一条不正确的UPDATE

时间:2013-10-26 09:15:59

标签: android android-canvas android-view ontouchevent motionevent

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

背景:

我创建了一个自定义视图,然后将这些视图添加到TableLayout,从而创建了一个网格点。我的目的是让我能够以某种方式从这些点中的一个点到另一个点画一条线,这样当按下一个点时,一条线从按下的点的中心开始到手指当前的点接触。当手指在另一个点上拖动时,该线在该点的中心处完成。结果是从被按压点的中心绘制到被手指拖过的点中心的线。

要在TableLayout上创建一条线,我创建了一个新的自定义视图,它只是使用canvas.drawLine()方法在点之间创建了一条线。然后我创建了一个FrameLayout,其中我放置了TableLayout和LineView。这意味着可以在TableLayout上绘制线条视图。

现状:

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

问题是获得正确的坐标来绘制线条。我已经尝试了很多方法来获取被按下的点中心的坐标(线的起点),但我仍然没有管理它。这个问题有更多信息:Get the coordinates of the center of a view。第二部分是获得该线的正确终点。出于这个问题的目的,我希望线的末端跟随手指的位置。我认为它就像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

Screenshot 2

如果需要任何其他信息/代码,我很乐意提供。

感谢您花时间阅读此内容 - 抱歉,这太长了!

1 个答案:

答案 0 :(得分:2)

  

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

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

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

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