Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/196.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在渲染到布局之前获取文本视图的高度_Android_Textview - Fatal编程技术网

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

Android 在渲染到布局之前获取文本视图的高度,android,textview,Android,Textview,在将textview呈现到布局之前,在设置文本的位置计算textview高度时,找不到任何好的解决方案。请提供任何帮助2个解决方案 最初使用了解决方案1,后来找到了解决方案2。两种方法都有效,这是你真正喜欢的 重要的是要确保所有尺寸都正确,因为在sp或px中混合字体大小会根据您测试的屏幕产生很大的差异 一个非常基本的示例项目可以在 解决方案1使用TextView和MeasureSpec 原始问题的主要问题是下面方法中的TextView应该配置为我们的TextView,它应该呈现给布局。我认为这个

在将textview呈现到布局之前,在设置文本的位置计算textview高度时,找不到任何好的解决方案。请提供任何帮助

2个解决方案 最初使用了解决方案1,后来找到了解决方案2。两种方法都有效,这是你真正喜欢的

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

一个非常基本的示例项目可以在

解决方案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();
        }
以及如何使用此功能的示例:

// 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); 
解决方案2使用TextPaint和StaticLayout 这个方法依赖于TextPaint和StaticLayout,它还提供了到目前为止我测试过的所有API级别的可靠结果。注意尺寸单位;所有都应该以像素为单位

资料来源:


从support_ms answer中,有一个更简单的方法,它只将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();
}

@support_ms的回答很好,但我不确定创建一个新的TextView并计算出所有这些输入参数的意义,因为您可以先格式化TextView,然后只使用一个参数调用静态方法,
TextView
本身

另外,我不确定为什么一个参数被标记为
deviceWidth
,我只是使用
Textview
本身的宽度。我的是
match_parent
,我想任何
TextView
包含
wrap_内容的
都可能根本不起作用。但这就是你得到的

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();
}

这是我的简单解决方案,它可以在喷漆前得到尺寸


在渲染之前获取文本视图的行

这是我基于上述想法编写的代码。这对我有用

private int widthMeasureSpec;
private int heightMeasureSpec;
private int heightOfEachLine;
private int paddingFirstLine;
private void calculateHeightOfEachLine() {
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = wm.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    int deviceWidth = size.x;
    widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(deviceWidth, View.MeasureSpec.AT_MOST);
    heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    //1 line = 76; 2 lines = 76 + 66; 3 lines = 76 + 66 + 66
    //=> height of first line = 76 pixel; height of second line = third line =... n line = 66 pixel
    int heightOfFirstLine = getHeightOfTextView("A");
    int heightOfSecondLine = getHeightOfTextView("A\nA") - heightOfFirstLine;
    paddingFirstLine = heightOfFirstLine - heightOfSecondLine;
    heightOfEachLine = heightOfSecondLine;
}

private int getHeightOfTextView(String text) {
    // Getting height of text view before rendering to layout
    TextView textView = new TextView(context);
    textView.setPadding(10, 0, 10, 0);
    //textView.setTypeface(typeface);
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources().getDimension(R.dimen.tv_size_14sp));
    textView.setText(text, TextView.BufferType.SPANNABLE);
    textView.measure(widthMeasureSpec, heightMeasureSpec);
    return textView.getMeasuredHeight();
}

private int getLineCountOfTextViewBeforeRendering(String text) {
    return (getHeightOfTextView(text) - paddingFirstLine) / heightOfEachLine;
}
注意:此代码也必须为屏幕上的real textview设置

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources().getDimension(R.dimen.tv_size_14sp));

您试图做的事情可能有问题。如果将高度设置为某个值(如60dp),则可以,但如果将其设置为“包裹内容”,则高度将取决于屏幕大小。因此,您可能希望以编程方式(用Java代码)创建textview。我正在创建电子书阅读器,为此,我应该知道textview的高度文本适合它的大小。如果您将其设置为“wrap_content”,它将根据其内容展开。如果您想确保用户不应垂直滑动,则可以查看viewflipper、viewpager等。您是否检查了此[问题]()@MobileListrici文本中有可扩展文本和不同字体,我无法计算一页有多少文本足够。这就是为什么我将文本按空格分割,添加每个元素后,它应该检查textview是否超过显示高度。为此,我应该知道textview的高度,并在每次添加textview之前进行检查如果文本包含任何将以显示的文本视图大小换行的行,则MeasureSpec.AT_最为重要。为什么此处顶部填充为0?@treesareverywhere不重要。这只是为了我的案子,我试过了,几乎奏效了。但是,最后一行文本被截断。我试着测试这个,在里面放了很多很长的乱七八糟的单词,超过20个字符,行被截断的数量增加了。我只能假设这个测量的高度没有考虑到下一行的单词溢出。因此,这个计算的高度小于实际渲染的高度,随着字数的增加和文本的加长,差异越来越大。@Distribution我应该使用EditText makeMeasureSpec或inflate上的EditText设置。至少对于单行文本视图来说,这个设置非常有效。(这就是我需要的)。请注意,由于设备的实际像素宽度通常是已知的(它通常用于应用程序的其他部分),并且变量“wm”未使用,因此只有这段代码的最后四行就足够了。伟大的工作起来很有魅力。:)令人惊叹的!谢谢你,好心的先生!这个屏幕宽度方法是什么?这个方法在其他SO答案中可用。为了清晰起见,我添加了这个方法。
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, context.getResources().getDimension(R.dimen.tv_size_14sp));