get position of the text inside a TextView
Take a look at a couple of Paint
methods: getTextBounds()
and measureText
. We can use these to determine the offset of the text within the TextView
. Once the offset within the TextView
is determined, we can add that to the location of the TextView
itself to determine the screen coordinates of the text if that is desired.
I have also found the article "Android 101: Typography" to be useful in understanding some of the complexities of typography.
The following example finds the bounds of the text within three TextViews
and draws a rectangle around the text. The rectangle contains the (x, y) coordinates of the text within the TextView
.
activity_main.xml
A simple layout for demonstration.
<android.support.constraint.ConstraintLayout
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="@android:color/holo_blue_light"
android:padding="24dp"
android:text="Hello World"
android:textColor="@android:color/black"
android:textSize="50sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="@android:color/holo_blue_light"
android:padding="24dp"
android:text="Hello Worldly"
android:textColor="@android:color/black"
android:textSize="50sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView1" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:background="@android:color/holo_blue_light"
android:padding="24dp"
android:text="aaaaaaaaaa"
android:textColor="@android:color/black"
android:textSize="50sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/textView2" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawTextBounds((TextView) findViewById(R.id.textView1));
drawTextBounds((TextView) findViewById(R.id.textView2));
drawTextBounds((TextView) findViewById(R.id.textView3));
}
private void drawTextBounds(TextView textView) {
// Force measure of text pre-layout.
textView.measure(0, 0);
String s = (String) textView.getText();
// bounds will store the rectangle that will circumscribe the text.
Rect bounds = new Rect();
Paint textPaint = textView.getPaint();
// Get the bounds for the text. Top and bottom are measured from the baseline. Left
// and right are measured from 0.
textPaint.getTextBounds(s, 0, s.length(), bounds);
int baseline = textView.getBaseline();
bounds.top = baseline + bounds.top;
bounds.bottom = baseline + bounds.bottom;
int startPadding = textView.getPaddingStart();
bounds.left += startPadding;
// textPaint.getTextBounds() has already computed a value for the width of the text,
// however, Paint#measureText() gives a more accurate value.
bounds.right = (int) textPaint.measureText(s, 0, s.length()) + startPadding;
// At this point, (x, y) of the text within the TextView is (bounds.left, bounds.top)
// Draw the bounding rectangle.
Bitmap bitmap = Bitmap.createBitmap(textView.getMeasuredWidth(),
textView.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
Paint rectPaint = new Paint();
rectPaint.setColor(Color.RED);
rectPaint.setStyle(Paint.Style.STROKE);
rectPaint.setStrokeWidth(1);
canvas.drawRect(bounds, rectPaint);
textView.setForeground(new BitmapDrawable(getResources(), bitmap));
}
}
Y value
You can use textView.getTextSize()
or textView.getPaint().getTextSize()
to get the actual used text size in pixels (as Float
).
Next, we need the total height of the text view, which we can find as follows:
textView.measure(0, 0); // We must call this to let it calculate the heights
int height = textView.getMeasuredHeight();
However, the final size that we need can also have decimals. So lets make it a float for more precision:
float totalHeight = (float) height;
Now that we know the values, we can calculate the y value of the text inside the view:
// The spacing between the views is `totalHeight - textSize`
// We have a spacing at the top and the bottom, so we divide it by 2
float yValue = (totalHeight - textSize) / 2
X value
Furthermore, the xValue is just the x value of the text view itself when using
android:includeFontPadding="false"
.