9

I want to calculate the line (or layout) height (in DP) which contains only TextView as outcome of the TextView text size when using default line spacing ?
I.E. for this layout :

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/minRow1col1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:textIsSelectable="false"
        android:textSize="11dp" />  

</LinearLayout>

What will be the layout/line height ? (any formula ? I don't need the value in run time)

Thanks !

SagiLow
  • 5,721
  • 9
  • 60
  • 115

5 Answers5

16

I don't know if this help you guys, but my solution to get the height of a line it's independent of the height of the layout, just take the font metrics like this:

myTextView.getPaint().getFontMetrics().bottom - myTextView.getPaint().getFontMetrics().top)

With this you will get the line height and for me, it's works with all words ( there are some chars like "g" or "j" that take some bottom space, the so called "descender" and so on ).

jfcogato
  • 3,359
  • 3
  • 19
  • 19
  • As I can remember, it's px. – jfcogato Jan 03 '19 at 12:50
  • It always is px when you deal with Paint and most Android Apis. –  Feb 04 '19 at 11:57
  • The answer yields the correct value, but it should be noted, that fontMetrics.top and fontMetrics.bottom don't actually stand for what you might think they stand for. Top: The maximum distance above the baseline for the tallest glyph in the font at a given text size. Bottom: The maximum distance below the baseline for the lowest glyph in the font at a given text size. The only reason why bottom - top leads to the correct value, is because top is negative: Remember, Y values increase going down, so those values will be positive, and values that measure distances going up will be negative. –  Feb 04 '19 at 12:44
5

Try using the TextPaint object of TextView.

TextView tv = useTextView;
String text = tv.getText().toString();
Paint textPaint = tv.getPaint();

Rect textRect = new Rect();
textPaint.getTextBounds(text, 0, text.length(), textRext);

int textHeight = textRect.height();

Per documentation of Paint#getTextBound:

Return in bounds (allocated by the caller) the smallest rectangle that encloses all of the characters, with an implied origin at (0,0).

Using the Paint object that the TextView uses will ensure it has the same parameters set that will be used to draw the text.

DeeV
  • 35,865
  • 9
  • 108
  • 95
  • What will happen in case of a Spanned text. Each line may be of a different height. If you do a toString(), all the spanned information will be lost. How do you deal with such a case? – Ashwin Aug 03 '15 at 10:24
  • @Ashwin TextView uses a Spanned internally for editable text. You have to call it each time the text changes, but you should get the shortest height of the current text. – DeeV Aug 03 '15 at 13:52
0

You can try Paint.getTextBounds():

String finalVal ="Hello";

Paint paint = new Paint();
paint.setTextSize(18);  
paint.setTypeface(Typeface.SANS_SERIF);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);

Rect result = new Rect();
// Measure the text rectangle to get the height
paint.getTextBounds(finalVal, 0, finalVal.length(), result);

Log.d("WIDTH        :", String.valueOf(result.width()));
Log.d("HEIGHT       :", String.valueOf(result.height()));

Source.

Community
  • 1
  • 1
Pull
  • 2,236
  • 2
  • 16
  • 32
  • I just need to know the `formula` not the size on run time. – SagiLow Nov 27 '13 at 16:31
  • what the numbers i get represent ? DP ? PX ? Because I measured my printscreens and got different values. Also, I get for 8 larger value than 9. – SagiLow Nov 27 '13 at 18:20
  • As the fonction getTextBounds is drawing a rectangke, I would say in DP so depending on the screen density of pixel, but I cannot be sure – Pull Nov 27 '13 at 21:25
  • @Pull: you only ever get DP when talking in the context of getResources(). Any bounds/positions are always in raw converted pixel values. – David Liu Apr 15 '15 at 22:49
0

You have to create custom Textview and use getActualHeight() method. Where the formula is: actualHeight=(int) ((getLineCount()-1)*getTextSize());

public class TextViewHeightPlus extends TextView {
    private static final String TAG = "TextView";
    private int actualHeight=0;


    public int getActualHeight() {
        return actualHeight;
    }

    public TextViewHeightPlus(Context context) {
        super(context);
    }

    public TextViewHeightPlus(Context context, AttributeSet attrs) {
        super(context, attrs);
        setCustomFont(context, attrs);
    }

    public TextViewHeightPlus(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

    }

   @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        actualHeight=0;

        actualHeight=(int) ((getLineCount()-1)*getTextSize());

    }

}
Veaceslav Gaidarji
  • 4,261
  • 3
  • 38
  • 61
0

For my usecase I started out by assuming that the line height is a linear function that depends on the textsize, something like:

line_height = text_size*some_constant

Now some_constant is probably a function as well, that depends on what font you use. But since in my requirements the font was static, I was able to calculate some_constant and use repeatedly in a safe way.

To clue you in a little a bit more on my usecase, I was scaling a piece of multiline text in order to fit it in a box of variable height.

In my usecase I wanted to go a step further and included the space multiplier. It was quite simple, as it was just another factor in the equation:

line_height = text_size*some_constant*spacing_multiplier

In summary if you stick to the same font and you calculate the value of some_constant once, you can (probably) get your function.

DISCLAIMER: I say "probably" a lot because I haven't tested a lot of my assumptions, but like I said, it worked for a decently complex usecase.

rfreitas
  • 76
  • 1
  • 2