Currently I'm using paintObject.measureText(textCopy.substring(0,i))
while iterating through a copy of the TextView's text. For example, measureText("abc".substring(0,1))
will give me the relative x coordinates of 'b'. The y coordinate I get from layout.getLineTop()
. This is working but not accurate for x coordinates for non-monospaced fonts. I can calibrate a little, but on each device it works differently.
The best solution I can think of is to overwrite the class that is responsible for drawing the TextView on the screen and, hopefully, get the coordinates of each character drawn to screen.
Does anyone know what class I need to overwrite to accomplish this? Or maybe some other creative solution?
Well it seems sort of a bug of Paint.measureText()
or other deeper class. But I have FINALLY found a way around it:
layout.getPrimaryHorizontal(int offset)
This is very easy. You just iterate through the layout using the length of the text it uses.
It will return the the x of the Character REGARDLESS of line position. So lines I'm still getting from the layout.getLineTop()
. By the way, if you are using the layout.getLineTop()
, note that there is some strange behaviour, possibly a bug. I have submitted a bug report here.
Here is the full code for how to get the x
and y
coordinates of a specific character. offset
is the index of the desired character in the textView
's text. These coordinates are relative to the parent container
Layout layout = textView.getLayout();
if (layout == null) { // Layout may be null right after change to the text view
// Do nothing
}
int lineOfText = layout.getLineForOffset(offset);
int xCoordinate = (int) layout.getPrimaryHorizontal(offset);
int yCoordinate = layout.getLineTop(lineOfText);
If you expect to use this more than once:
fun TextView.charLocation(offset: Int): Point? {
layout ?: return null // Layout may be null right after change to the text view
val lineOfText = layout.getLineForOffset(offset)
val xCoordinate = layout.getPrimaryHorizontal(offset).toInt()
val yCoordinate = layout.getLineTop(lineOfText)
return Point(xCoordinate, yCoordinate)
}
NOTE: To ensure layout is not null, you can call
textview.post(() -> { /* get coordinates */ })
in Java ortextview.post { /* get coordinates */ }
in Kotlin
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With