Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measure height of multi-line TextView before rendering

What i've tried to far:

  1. Calling measure()

    tv.measure(0, 0);
    int height = tv.getMeasuredHeight();
    
  2. Calling measure() with specified sizes/modes

    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(99999, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    tv.measure(widthMeasureSpec, heightMeasureSpec);
    int height = tv.getMeasuredHeight();
    
  3. Calling getTextBounds()

    Rect bounds = new Rect();
    tv.getPaint().getTextBounds(tv.getText().toString(), 0, tv.getText().length(), bounds);
    int height = bounds.height();
    
  4. Calling measure() and then calling getTextBounds()

  5. Calling getLineCount() * getLineHeight()

None seem to work. They all return incorrect values (container view gets incorrect height - it's either too small or too large)

Ideas on how to calculate this simple thing??

like image 614
Shai Avatar asked Jun 02 '15 08:06

Shai


1 Answers

You need to specify the available width so the height can be properly calculated.

Note: In cases where you just need to get the height of a view that is already drawn, use ViewTreeObserver. See this question for a thing to consider in that case.

This is why I do, in a piece of code where I want to scale a view from hidden to its full necessary height:

int availableWidth = getParentWidth(viewToScale);

int widthSpec = View.MeasureSpec.makeMeasureSpec(availableWidth, View.MeasureSpec.AT_MOST);
int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);

viewToScale.measure(widthSpec, heightSpec);
int measuredHeight = viewToScale.getMeasuredHeight();
// Offtopic: Now I animate the height from 1 to measuredHeight (0 doesn't work)

You may pass the availableWidth yourself, but I calculate it from the parent:

private int getParentWidth(View viewToScale)
{
    final ViewParent parent = viewToScale.getParent();
    if (parent instanceof View) {
        final int parentWidth = ((View) parent).getWidth();
        if (parentWidth > 0) {
            return parentWidth;
        }
    }

    throw new IllegalStateException("View to scale must have parent with measured width");
}
like image 50
Ferran Maylinch Avatar answered Sep 29 '22 20:09

Ferran Maylinch