0

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;
}
Ziad H.
  • 528
  • 1
  • 5
  • 20
  • 1
    can show a bit more code how and where are you handling your touch events. – Syed Ahmed Jamil Nov 27 '19 at 18:40
  • Ok, I updated the post. Thanks :D – Ziad H. Nov 27 '19 at 19:00
  • actually the colour changing means that you will actually be redrawing the same `Rect` with a different colour. Where are you drawing your `Rect`, in `onDraw()` ? Can you show it ? I'm assuming you are passing this `color` variable to the `Paint` object in onDraw(). Also I see you are using `postInvalidate()` instead of just `invalidate()` are you calling this from a different thread ? – Syed Ahmed Jamil Nov 27 '19 at 19:21
  • You can check that in the TextGraphic and GraphicOverlay classes I referred to. Here are the links again: https://github.com/firebase/quickstart-android/blob/master/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/java/textrecognition/TextGraphic.java https://github.com/firebase/quickstart-android/blob/master/mlkit/app/src/main/java/com/google/firebase/samples/apps/mlkit/common/GraphicOverlay.java I'm sorry but I'm not really comfortable with using/drawing rects so i'm kinda' lost – Ziad H. Nov 27 '19 at 19:29
  • What do you mean by "all Rect colour is changed and they don't change at run time". Its a bit vague. When you say they don't change at run-time I assume your rects are not changing colour at all on click when app is running. But you are also saying that all rect colours are changed. Can you clarify ? – Syed Ahmed Jamil Nov 27 '19 at 19:32
  • Well, What I want to do is something like picture translating on google translate; when you swipe over some words, they get highlighted. But the problem is that code I'm using right now is changing the color of all rects. Second problem, is that this doesn't happen on runtime! How do I know? well, rects change color when I choose a new photo, because choosing a new photo refreshes all rects and draw new ones. – Ziad H. Nov 27 '19 at 19:41
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/203202/discussion-between-syed-ahmed-jamil-and-ziad-h). – Syed Ahmed Jamil Nov 27 '19 at 19:45

2 Answers2

1

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.

Syed Ahmed Jamil
  • 1,881
  • 3
  • 18
  • 34
  • Thanks a lot, master Syed! your solution was perfect. And yes, I was able to fix the problem that you mentioned in your side note, by resetting the arraylist of rectangles everytime a new image is set to be read :) – Ziad H. Dec 12 '19 at 16:22
0

Maybe you should not do it by coding but by ColorStateList Android Developer: colorstatelist