在渲染到布局之前获取文本视图的高度

sup*_*_ms 38 android textview

在将 textview 渲染到布局之前,无法找到任何计算文本视图高度的好方法.请帮忙

sup*_*_ms 66

2解决方案

首先使用解决方案1,稍后找到解决方案2.两者都有效,这真的是你喜欢的.

重要的是确保您拥有所有尺寸,因为在sp或px中混合字体大小会根据您测试的屏幕产生很大差异.

一个非常基本的示例项目可以在https://github.com/hanscappelle/SO-3654321上找到

解决方案1使用TextView和MeasureSpec

原始问题的主要问题是下面方法中的TextView应该被配置为我们的TextView,它应该被渲染为布局.我认为这个解决方案对于许多遇到这个问题的人来说很有价值.

public static int getHeight(Context context, CharSequence text, int textSize, int deviceWidth, Typeface typeface,int padding) {
            TextView textView = new TextView(context);
            textView.setPadding(padding,0,padding,padding);
            textView.setTypeface(typeface);
            textView.setText(text, TextView.BufferType.SPANNABLE);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
            int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
            int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
            textView.measure(widthMeasureSpec, heightMeasureSpec);
            return textView.getMeasuredHeight();
        }
Run Code Online (Sandbox Code Playgroud)

以及如何使用它的示例:

// retrieve deviceWidth
int deviceWidth;
WindowManager wm = (WindowManager) textView.getContext().getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
    Point size = new Point();
    display.getSize(size);
    deviceWidth = size.x;
} else {
    deviceWidth = display.getWidth();
}
// the text to check for
String exampleTextToMeasure = "some example text that will be long enough to make this example split over multiple lines so we can't easily predict the final height";
//  some dimensions from dimes resources to take into account
int textSize = getContext().getResources().getDimensionPixelSize(R.dimen.text_size);
int padding = getContext().getResources().getDimensionPixelSize(R.dimen.text_padding);

// final calculation of textView height
int measuredTextHeight = getHeight(getContext(), exampleTextToMeasure, textSize, deviceWidth, TypeFace.DEFAULT, padding); 
Run Code Online (Sandbox Code Playgroud)

解决方案2使用TextPaint和StaticLayout

这个方法依赖于TextPaint和StaticLayout,它也为我到目前为止测试的所有API级别提供了可靠的结果.要注意尺寸单位; 一切都应该是像素!

来源:测量Canvas(Android)上绘制的文字高度

    public static int method1UsingTextPaintAndStaticLayout(
            final CharSequence text,
            final int textSize, // in pixels
            final int deviceWidth, // in pixels
            final int padding // in pixels
    ) {

        TextPaint myTextPaint = new TextPaint();
        myTextPaint.setAntiAlias(true);
        // this is how you would convert sp to pixels based on screen density
        //myTextPaint.setTextSize(16 * context.getResources().getDisplayMetrics().density);
        myTextPaint.setTextSize(textSize);
        Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
        float spacingMultiplier = 1;
        float spacingAddition = padding; // optionally apply padding here
        boolean includePadding = padding != 0;
        StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, deviceWidth, alignment, spacingMultiplier, spacingAddition, includePadding);
        return myStaticLayout.getHeight();
    }
Run Code Online (Sandbox Code Playgroud)


Hug*_*sse 12

从support_ms回答,有一个更简单的方法,只接受TextView作为参数.

/**
 * Get the TextView height before the TextView will render
 * @param textView the TextView to measure
 * @return the height of the textView
 */
public static int getTextViewHeight(TextView textView) {
    WindowManager wm =
            (WindowManager) textView.getContext().getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();

    int deviceWidth;

    if(android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2){
        Point size = new Point();
        display.getSize(size);
        deviceWidth = size.x;
    } else {
        deviceWidth = display.getWidth();
    }

    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    textView.measure(widthMeasureSpec, heightMeasureSpec);
    return textView.getMeasuredHeight();
}
Run Code Online (Sandbox Code Playgroud)

  • 我试过这个,它几乎有效。但是,最后一行文本被切断了。我尝试对此进行测试,并在其中放入了很多非常长的胡言乱语 > 20 个字符,并且被截断的行数增加了。我只能假设这个测量的高度没有考虑到下一行的字溢出。所以这个计算的高度小于实际渲染的高度,随着更大的单词和更长的文本而增加差异。 (2认同)

And*_*sch 6

@support_ms的好答案,但是当您只需要先格式化TextView然后仅使用一个参数(TextView本身)调用静态方法时,我不确定创建新的TextView并计算所有这些输入参数的意义!

另外,我不确定为什么标记了一个参数,而deviceWidth只是使用其Textview自身的宽度。我的是match_parent,我想任何TextView有wrap_content可能无法在所有工作。但这就是你得到的。

public static int getHeight(TextView t) {
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(screenWidth(t.getContext()), View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    t.measure(widthMeasureSpec, heightMeasureSpec);
    return t.getMeasuredHeight();
}

public static int screenWidth(Context context)
{
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    return display.getWidth();
}
Run Code Online (Sandbox Code Playgroud)