Search code examples
javaandroidandroid-canvascoordinate-systems

how to correctly compare coordinates?


I have custom view with drawn text and with user drawn line.

Text have some (x,y) coordinates and line have it as well (as soon as user draws it). And I just want to compare, that line coordinates are somewhere the same as text's.

But since it's very hard to hit precise coordinates with finger, it's impossible to compare it directly for user it looks like he connected 2 texts, but coordinates are slightly different.

How can I do it correctly?

Here's my code for direct comparsion (method isCorrectConnection):

public class FingerLineView extends View {
    private final Paint mPaint;
    private final Paint mPaintText;
    private float startX, startY;
    private float endX, endY;

    public FingerLineView(Context context) {
        this(context, null);
    }

    public FingerLineView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.RED);
        mPaintText = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaintText.setColor(Color.BLACK);
        mPaintText.setTextSize(30);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawLine(startX, startY, endX, endY, mPaint);
        canvas.drawText("TEXT", 10, 200, mPaintText);
        canvas.drawText("TEXT", 200, 200, mPaintText);
    }

    @Override
    public boolean onTouchEvent(@NonNull MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();
                // Set the end to prevent initial jump
                endX = event.getX();
                endY = event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                endX = event.getX();
                endY = event.getY();
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                endX = event.getX();
                endY = event.getY();
                isCorrectConnection(startX, startY, endX, endY, 10, 200, 200, 200);
                invalidate();
                break;
        }
        return true;
    }

    public boolean isCorrectConnection(float startX, float startY, float endX, float endY,
                                       float textX1, float textY1, float textX2, float textY2) {
        return startX == textX1 && startY == textY1 && endX == textX2 && endY == textY2;
    }
}

Solution

  • Based on my understanding of your question you want to check if user clicks the first text and moved(dragged) to the second text or vice versa, you should check for pressing the entire text not just the top left of the drawn text, so I have an answer for you which the two text's should be different for knowing there size in pixels and then checking for touch inside this rectangle of text not just the top left point as I described, so let's start : First you should change your isCorrectConnection function to this instead:-

    private boolean isCorrectConnection(float startX, float startY, float endX, float endY,
                                       float x1, float y1, float x2, float y2
                                       String text1, String text2) {
        //Measuring text1's size
        Rect textBounds = new Rect();
        mPaint.getTextBounds(text1, 0, text1.length(), textBounds);
        int w1 = textBounds.width();
        int h1 = textBounds.height();
    
        //Measuring text2's size
        Rect textBounds2 = new Rect();
        mPaint.getTextBounds(text2, 0, text2.length(), textBounds2);
        int w2 = textBounds2.width();
        int h2 = textBounds2.height();
    
        //Checking for touched and moved from text1 to text2
        if(startX >= x1 && startX <= (x1 + w1) && startY >= y1 && startY <= (y1 + h1) &&
           endX >= x2 && endX <= (x2 + w2) && endY >= y2 && endY <= (y2 + h2))
            return true;
    
        //Checking for touched and moved from text2 to text1
        if(startX >= x2 && startX <= (x2 + w2) && startY >= y2 && startY <= (y2 + h2) &&
           endX >= x1 && endX <= (x1 + w1) && endY >= y1 && endY <= (y1 + h1))
            return true;
    
        return false;
    }
    

    And if you're sure that the texts are the same so do the following instead:-

    private boolean isCorrectConnection(float startX, float startY, float endX, float endY,
                                       float x1, float y1, float x2, float y2
                                       String text) {
        //Measuring text's size
        Rect textBounds = new Rect();
        mPaint.getTextBounds(text, 0, text.length(), textBounds);
        int w1 = textBounds.width(), w2 = w1;
        int h1 = textBounds.height(), h2 = h1;
    
        //Checking for touched and moved from text1 to text2
        if(startX >= x1 && startX <= (x1 + w1) && startY >= y1 && startY <= (y1 + h1) &&
           endX >= x2 && endX <= (x2 + w2) && endY >= y2 && endY <= (y2 + h2))
            return true;
    
        //Checking for touched and moved from text2 to text1
        if(startX >= x2 && startX <= (x2 + w2) && startY >= y2 && startY <= (y2 + h2) &&
           endX >= x1 && endX <= (x1 + w1) && endY >= y1 && endY <= (y1 + h1))
            return true;
    
        return false;
    }