androidhighlightfirebase-mlkittext-recognitionandroid-rect

How to change color of Rects instantly when touched?


I'm working in an app that uses the ml kit text recognition library; The app reads text from images and puts a Rect around every word. Now I want these Rects to change color when the user tap on one of them or swipe above some words. So, I was able to handle touch events correctly, but what I can't do is changing the color of the touched Rect!

Should I draw new colored Rects above the touched Rect? Or can I color the existing rects (which I don't think I can)?

Classes: TextGraphic, GraphicOverlay. //This is where the Rects get drawn

I also tried this solution, so I typed this methods in the TextGraphic class:

public void changeColor(boolean isHighlighted) {
    if(isHighlighted) {
        rectPaint.setColor(COLOR_HIGHLIGHTED);
        rectPaint.setAlpha(400);//set opacity of rect
    }else{
        rectPaint.setColor(COLOR_DEFAULT);
        rectPaint.setAlpha(400);//set opacity of rect
    }
    postInvalidate();
}

and called it when the user touches the text, but the problem is that all Rects colors get changed, and they do not change at runtime!

A snippet from my ActivityClass, where I used some callback methods to pass things out.

ArrayList<Rect> rects = new ArrayList<>();

@Override
public void onAdd(FirebaseVisionText.Element element, Rect elementRect, String wordText) {
   GraphicOverlay.Graphic textGraphic = new TextGraphic(mGraphicOverlay, element);
   mTextGraphic = new TextGraphic(mGraphicOverlay, element);
   mGraphicOverlay.add(textGraphic);


   rects.add(elementRect);
}

A snippet from my ActivityClass where I handle touch events:

@Override
public boolean onDown(MotionEvent event) {
   helper.dismissKeyboard();
   touchX = Math.round(event.getX());
   touchY = Math.round(event.getY());
   for(int x=0; x< rects.size();x++) {
       if (rects.get(x).contains(touchX, touchY)) {
           // line has been clicked
           mTextGraphic.changeColor(true);

           return true;
       }
   }
   return true;
}

Solution

  • You are changing the color using the mTextGraphic variable. If you look closely in your onAdd() method you will see that you are assigning a new object to mTextGraphic that has nothing to do with the objects drawn to screen because only the objects that you add to GraphicOverlay list using the mGraphicOverlay.add() will get drawn to screen.

    So what you need is to call changeColor() not on mTextGraphic but on the respective object that is already in the list inside GraphicOverlay

    Since the list inside GraphicOverlay is private you can't manipulate it in the onDown() method. You will need to write a public method that will do the job for you.

    Write the following method in GraphicOverlay class

    public TextGraphic getGraphicElementAtIndex(int index) {
        return (TextGraphic)graphics.get(index)
    }
    

    Now use this method inside the if condition of onDown() method like this

    if (rects.get(x).contains(touchX, touchY)) {
        // line has been clicked
        Log.d("PreviewActivity", "changeColor() is called");
        mGraphicOverlay.getGraphicElementAtIndex(x).changeColor();
        touchedText = texts.get(x);
        return true;
    }
    

    Hope this helps.

    SIDE NOTE: Now even after this if for some reason the ordering of objects inside rects list and graphics list (which is inside GraphicOverlay) change then you will see that when you click a rectangle some other rectangle changes color.