如何找到每行的TextView Text字符数?

时间:2011-05-11 21:08:08

标签: android text size width textview

所以我在android中有一个TextView,它具有屏幕整个长度的宽度和dip 5的填充。如何计算屏幕上适合单行的字符数?我想换句话说,我正在尝试获取textview的列数?

我考虑了手工计算取决于文本大小和宽度,但是1)不知道相关性和2)由于以dip为单位的填充,不同的屏幕将使用不同数量的实际像素来填充。

总体问题:我正在尝试使用它来解决:如果给出一个字符串,我怎样才能手动编辑为字符串,以便当textview按字符打印字符串时,我将知道何时开始一个不会出现的字符串适合下一行。注意:我知道textview会自动放入不适合下一行的单词,但是,由于我是逐个字符打印,比如输入动画,textview不知道这个单词在打印出来之前是不适合的这个词的字符溢出。

到处寻找这个......

谢谢!

添加了解决方案:

一种可能的解决方案:

public String measure2 (TextView t, String s) {
    String u = "";
    int start = 0;
    int end = 1;
    int space = 0;
    boolean ellipsized = false;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        float twidth = t.getPaint().measureText(s.substring(start, end));
        if (twidth < fwidth){
            if (end < s.length())
                end++;
            else {
                if (!ellipsized)
                    return s;
                return u + s.subSequence(start, end);
            }
        }
        else {
            ellipsized = true;
            space = (u + s.substring(start, end)).lastIndexOf(" ");
            if (space == -1)
                space = end - 1;
            u += s.subSequence(start, space) + "\n";
            start = space + 1;
            end = start + 1;
        }
    }
}

解决方案2,但有时仍使用solution1:

public String measure3 (TextView t, String s) {
    List<String> wlist = Arrays.asList(s.split(" "));
    if (wlist.size() == 1)
        return measure2(t, s);
    String u = "";
    int end = 1;
    float fwidth = t.getMeasuredWidth();
    for(;;) {
        //t.setText(s.substring(start, end));
        if (wlist.isEmpty())
            return u;
        String temp = listStr(wlist, end);
        float twidth = t.getPaint().measureText(temp);
        if (twidth < fwidth){
            if (end < wlist.size())
                end++;
            else {
                return u + temp;
            }
        }
        else {
            temp = listStr(wlist, end-1);
            if (end == 1)
                temp = measure2(t, temp);
            if (wlist.isEmpty())
                return u + temp;
            else
                u = u + temp + "\n";
            wlist = wlist.subList(end - 1, wlist.size());
            end = 1;
        }
    }
}

public String listStr (List<String> arr, int end) {
    String s = "";
    for (String e : arr.subList(0, end) ){
        s = s + e + " ";
    }
    return s.trim();
}

我使用上面的代码生成一个原始字符串s,一个将被打印的字符串u。但是,我认为这种方法效率很低。还有其他方法或更好的算法吗?注意:我修复了measure3中的一些错误,但是懒得编辑

3 个答案:

答案 0 :(得分:28)

试试这个:

private boolean isTooLarge (TextView text, String newText) {
    float textWidth = text.getPaint().measureText(newText);
    return (textWidth >= text.getMeasuredWidth ());
}

由于字符的宽度可变,检测到适合的字符数是不可能的。上面的函数将测试TextView中是否符合特定字符串。 newText的内容应该是特定行中的所有字符。如果为true,则启动一个新行(并使用新字符串作为参数传递)。


回答评论:

  1. 因为应用程序可以在许多系统中运行正是为什么您需要对其进行测量。
  2. 这是一种解决“整体问题”的方法。使用str.size()>numCol vs之间有什么区别?您需要实现动画(提示#1:插入换行符)
  3. 正如我之前所说,当你开始一个新行时,你开始一个新的字符串(提示#2:如果扩展TextView,你可以在覆盖setText时实现所有这些)。 (提示#3:跟踪使用static int lines;创建的行并使用newString.split("\\r?\\n")[lines-1]检查长度。)

答案 1 :(得分:1)

您可以通过以下代码获取Textview的总行数并获取每个字符的字符串。然后您可以将样式设置为您想要的每一行。

我将第一行设为粗体。

private void setLayoutListner( final TextView textView ) {
        textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                textView.getViewTreeObserver().removeGlobalOnLayoutListener(this);

                final Layout layout = textView.getLayout();

                // Loop over all the lines and do whatever you need with
                // the width of the line
                for (int i = 0; i < layout.getLineCount(); i++) {
                    int end = layout.getLineEnd(0);
                    SpannableString content = new SpannableString( textView.getText().toString() );
                    content.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, end, 0);
                    content.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), end, content.length(), 0);
                    textView.setText( content );
                }
            }
        });
    }

试试这种方式。你可以用这种方式应用多种风格。

答案 2 :(得分:0)

我遇到了同样的问题,我通过2个步骤计算了每行的字符数: 步骤1:计算行数

import matplotlib.pyplot as plt

x =  [(370, 560), (550,980), (380,440)]

def activity_filler(x,y1,y2):
    # Shade the area between y1 and y2
    plt.fill_between(x, y1, y2,
                     facecolor="grey", # The fill color
                     color='grey',       # The outline color
                     alpha=0.4, hatch = 'X\/|-')          # Transparency of the fill
activity_filler(x[0],[1],[2])
activity_filler(x[1],[2],[3])
activity_filler(x[2],[3],[4])
plt.show()

第2步:计算每行的字符数

 mAuth.createUserWithEmailAndPassword(email, password)
    .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
        @Override
        public void onComplete(@NonNull Task<AuthResult> task) {
            if (task.isSuccessful()) {

                // user account created successfully
                showMessage("Account created");
                // after we created user account we need to update his profile picture and name
                updateUserInfo(name, pickedImgUri, mAuth.getCurrentUser());

            } else {

                // account creation failed
                showMessage("account creation failed" + task.getException().getMessage());
                regBtn.setVisibility(View.VISIBLE);
                loadingProgress.setVisibility(View.INVISIBLE);

            }
        }
    });