我正在开发一个应用程序,它经常需要在TextView中向用户显示结果,就像某种日志一样。
该应用程序运行良好,它在TextView中显示结果,但只要它继续运行并添加行,由于TextView的字符长度,应用程序变慢并崩溃。
我想知道android API是否提供了强制TexView自动删除引入的最旧行以便为新的行腾出空间的方法。
答案 0 :(得分:8)
我遇到了同样的问题。我刚解决了。
诀窍是使用TextView的getEditableText()
方法。它有replace()
方法,甚至是delete()
方法。当您在其中附加行时,TextView已标记为“可编辑”,这是使用getEditableText()
所必需的。我有类似的东西:
private final static int MAX_LINE = 50;
private TextView _debugTextView; // Of course, must be filled with your TextView
public void writeTerminal(String data) {
_debugTextView.append(data);
// Erase excessive lines
int excessLineNumber = _debugTextView.getLineCount() - MAX_LINE;
if (excessLineNumber > 0) {
int eolIndex = -1;
CharSequence charSequence = _debugTextView.getText();
for(int i=0; i<excessLineNumber; i++) {
do {
eolIndex++;
} while(eolIndex < charSequence.length() && charSequence.charAt(eolIndex) != '\n');
}
if (eolIndex < charSequence.length()) {
_debugTextView.getEditableText().delete(0, eolIndex+1);
}
else {
_debugTextView.setText("");
}
}
}
问题是,TextView.getLineCount()
返回包装行的数量,而不是文本中“\ n”的数量......这就是为什么如果我到达文本的末尾我清除整个文本的原因在寻找要删除的行时。
您可以通过删除多个字符而不是删除多行而以不同方式执行此操作。
答案 1 :(得分:7)
此解决方案会跟踪列表中的日志行,并在每次更改时使用列表内容覆盖textview。
private List<String> errorLog = new ArrayList<String>();
private static final int MAX_ERROR_LINES = 70;
private TextView logTextView;
public void addToLog(String str) {
if (str.length() > 0) {
errorLog.add( str) ;
}
// remove the first line if log is too large
if (errorLog.size() >= MAX_ERROR_LINES) {
errorLog.remove(0);
}
updateLog();
}
private void updateLog() {
String log = "";
for (String str : errorLog) {
log += str + "\n";
}
logTextView.setText(log);
}
答案 2 :(得分:1)
TextView
显示您通过setText()
方法设置的内容。所以这听起来像你应该减少你提供的输入。
要清空TextView,您可以执行setText("");
答案 3 :(得分:1)
以下示例将行添加到由设置的最大行限制的输出日志中。添加每一行后,scrollview将自动滚动到底部。此示例完全使用TextView的内容,因此不需要单独的数据集合。
将以下内容添加到您的活动xml:
<ScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" >
<TextView
android:id="@+id/textViewOutput"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1000" />
</ScrollView>
在您的活动中添加以下代码:
private static final int MAX_OUTPUT_LINES = 50;
private static final boolean AUTO_SCROLL_BOTTOM = true;
private TextView _textViewOutput;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
_textViewOutput = (TextView) findViewById(R.id.textViewOutput);
}
//call to add line(s) to TextView
//This should work if either lineText contains multiple
//linefeeds or none at all
private void addLinesToTextView(String lineText) {
_textViewOutput.append(lineText);
removeLinesFromTextView();
if(AUTO_SCROLL_BOTTOM)
_scrollView.post(new Runnable() {
@Override
public void run() {
_scrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
// remove leading lines from beginning of the output view
private void removeLinesFromTextView() {
int linesToRemove = _textViewOutput.getLineCount() - MAX_OUTPUT_LINES;
if (linesToRemove > 0) {
for (int i = 0; i < linesToRemove; i++) {
Editable text = _textViewOutput.getEditableText();
int lineStart = _textViewOutput.getLayout().getLineStart(0);
int lineEnd = _textViewOutput.getLayout().getLineEnd(0);
text.delete(lineStart, lineEnd);
}
}
}
答案 4 :(得分:0)
我认为您正在使用TextView.append(string)
,然后它会添加到旧文本中
如果您使用setText
进行设置,则会替换旧文本
答案 5 :(得分:0)
这是一个旧的,但我刚刚找到了解决我自己问题的方法。
我可以使用LinearLayout
nameoflayout.removeAllViews();
删除所有TextView
还有另一种方法可以让你使用整数删除布局中指定位置的视图,它是:nameoflayout.removeViews(start, count);
所以我确定你可以创建一个超时文本视图保持可见的时间。
答案 6 :(得分:0)
尝试编写一个函数,该函数在TextView
上接受旧字符串并向其添加新字符串,然后获取子字符串TextView
能够使用的最后一个字符串。并将其设置为TextView
。像这样:
String str = textview.getText();
str += newstring;
int ln = str.length();
ln = ln-250;
if (ln<0) ln=0;
str = str.substring(ln);
textview.setText(str);
答案 7 :(得分:0)
不,android API不提供任何功能,可以自动从textview中删除最旧的行,直到API级别25.你需要在逻辑上这样做。
答案 8 :(得分:0)
参考Vincent Hiribarren的答案。 简单点->
TextView _debugTextView;
//if excess 20 lines keep new 200 chars
if(_debugTextView.getLineCount() >20) _debugTextView.getEditableText().delete(0,_debugTextView.getText().length()-200);