如何查找每行的 android TextView 字符数?
Posted
技术标签:
【中文标题】如何查找每行的 android TextView 字符数?【英文标题】:How to find android TextView number of characters per line? 【发布时间】:2011-08-23 15:51:12 【问题描述】:所以我在 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,但有时仍使用解决方案 1:
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 有一些错误我已经修复了,但是懒得编辑了
【问题讨论】:
我不认为默认字体是固定宽度的。因此,例如,它适合的 Ms 比 Is 少。如果您包含固定宽度的字体,那么找出的一种方法是继续添加到字符串并将其设置为视图,然后在屏幕上手动计算它们。它也会因不同的屏幕而有所不同,但这可能会导致您的使用出现问题。 我会看看这个问题***.com/questions/6272614/… @Derek 你能更新 measure3 函数吗?我想使用这个解决方案。谢谢 @Derek 最后我得到了解决方案,你也应该试试这个***.com/a/56753731/6676310 【参考方案1】:我遇到了同样的问题,我通过 2 个步骤计算了每行的字符数: 第一步:计算行数
val widthOfTvComment = widthOfScreen - marginLeft - marginRight
var bounds = Rect()
var paint = Paint()
paint.textSize = textSize
paint.getTextBounds(comment,0,comment.length,bounds)
val lines = ( bounds.width()/widthOfTvComment)
第 2 步:计算每行的字符数
val charactersPerLine = comment.length / lines
【讨论】:
我相信这是一个近似值!【参考方案2】:试试这个:
private boolean isTooLarge (TextView text, String newText)
float textWidth = text.getPaint().measureText(newText);
return (textWidth >= text.getMeasuredWidth ());
由于字符的宽度可变,因此无法检测出适合多少字符。上述函数将测试特定字符串是否适合 TextView。 newText 的内容应该是特定行中的所有字符。如果为真,则开始新行(并使用新字符串作为参数传递)。
回复评论:
-
因为该应用程序可以在许多系统中运行是正是您需要衡量它的原因。
这是一种解决“整体问题”的方法。使用
str.size()>numCol
vs is too large 有什么区别?您需要实现动画(提示 #1:插入换行符)
正如我之前所说,当你开始一个新行时,你开始一个新字符串(提示 #2:如果你扩展 TextView,你可以在覆盖 setText
中实现所有这些)。 (提示 #3:跟踪使用 static int lines;
创建的行并使用 newString.split("\\r?\\n")[lines-1]
检查长度)。
【讨论】:
我正在设置字体大小,但由于我更喜欢在多个系统上使用该应用程序,因此我不会手动计算长度。此外,当第一次发生溢出时,您的 isTooLarge 可用于获取字符串的长度,但是,它仍然会使第一行受到 textview 的椭圆动画的影响。感谢您的帮助,但我需要一些东西来让我知道 textview 何时会为每一行变成椭圆。 @Derek I 回复太长,所以我添加到答案中 好的,所以我在我编辑的问题中发布了我的解决方案,有没有更有效的方法? @Derek - 首先,我看到您一次测量一个字符。您有兴趣知道整个单词是否适合,因此将字符串分成单词 (str.split(" ")
) 并循环遍历单词。其次,首先测试功能。真的那么低效吗?您是否注意到任何延迟?
我明白你的意思,所以我做了 measure3,但是,我不知道为什么,但是即使你有一个没有空格的巨大字符串,textview 也会省略,所以 measure2 必须用于以下情况单个单词超出了宽度,但是 measure3 确实使用了 str.split(" ") ,这确实提高了效率。我意识到我在这个应用程序上所做的事情并没有滞后,因为它只读取短到中等的字符串,但是说我在另一个应用程序中使用这个功能,无论出于什么原因需要一本书的一章或一些巨大的东西,有没有更有效的代码还是这种唯一的方法?【参考方案3】:
您可以通过下面的代码获取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 );
);
试试这个方法。你可以用这种方法应用多种样式。
【讨论】:
以上是关于如何查找每行的 android TextView 字符数?的主要内容,如果未能解决你的问题,请参考以下文章
如何在android中以编程方式查找TextView的文本区域(高度/宽度)
如何使用contextId使用'CLASS_NAME'查找'找到'android.widget.TextView':''multiple:fal