在Android中自动滚动TextView以将文本引入到视图中

我有一个dynamic添加文本的TextView

在我的main.xml文件中,我设置了使我的最大线19和滚动条垂直的属性。

.java文件中我使用textview.setMovementMethod(new ScrollingMovementMethod()); 允许滚动。

滚动效果很好。 只要19行被占用,并且添加了更多的行,就开始滚动。 问题是,我想要新的文字滚动到视图。

我写出textview.getScrollY()的值,不pipe什么(即使我手动向下滚动并添加一行文本),它都保持为0

因此textview.scrollTo(0, textview.getScrollY()); 对我没有任何帮助。

是否有另一种方法,我应该用来获取textview的垂直滚动量? 我读过的所有内容都表明,对于所有的意图和目的,我所做的工作应该是:

通过TextView的源代码挖了一些,但这是我想出了。 它并不要求你将TextView包装在一个ScrollView中,并且据我所知,完美地工作。

 // function to append a string to a TextView as a new line // and scroll to the bottom if needed private void addMessage(String msg) { // append the new string mTextView.append(msg + "\n"); // find the amount we need to scroll. This works by // asking the TextView's internal layout for the position // of the final line and then subtracting the TextView's height final int scrollAmount = mTextView.getLayout().getLineTop(mTextView.getLineCount()) - mTextView.getHeight(); // if there is no need to scroll, scrollAmount will be <=0 if (scrollAmount > 0) mTextView.scrollTo(0, scrollAmount); else mTextView.scrollTo(0, 0); } 

请让我知道,如果你发现这种情况下失败。 我会很高兴能够修复我的应用程序中的任何错误;)

编辑:我应该提到,我也使用

 mTextView.setMovementMethod(new ScrollingMovementMethod()); 

实例化我的TextView后。

在XML布局的TextView中使用android:gravity="bottom" 。 例如

 <TextView ... android:gravity="bottom" ... /> 

不要问我为什么它的作品。

这种方法唯一的问题是,如果你想要向上滚动文本视图,每次插入新文本时都会一直“拉下”到底部。

这是我用来滚动一直到我的聊天文本的底部…

 public void onCreate(Bundle savedInstanceState) { this.chat_ScrollView = (ScrollView) this.findViewById(R.id.chat_ScrollView); this.chat_text_chat = (TextView) this.findViewById(R.id.chat_text_chat); } public void addTextToTextView() { String strTemp = "TestlineOne\nTestlineTwo\n"; //append the new text to the bottom of the TextView chat_text_chat.append(strTemp); //scroll chat all the way to the bottom of the text //HOWEVER, this won't scroll all the way down !!! //chat_ScrollView.fullScroll(View.FOCUS_DOWN); //INSTEAD, scroll all the way down with: chat_ScrollView.post(new Runnable() { public void run() { chat_ScrollView.fullScroll(View.FOCUS_DOWN); } }); } 

编辑:这是XML布局

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <!-- center chat display --> <ScrollView android:id="@+id/chat_ScrollView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:layout_alignParentLeft="true"> <TextView android:id="@+id/chat_text_chat" android:text="center chat" android:layout_width="fill_parent" android:layout_height="fill_parent" android:singleLine="false" /> </ScrollView> </RelativeLayout> 

以前的答案没有正确的工作,但是这个工作。

创build一个TextView并执行以下操作:

 // ... mTextView = (TextView)findViewById(R.id.your_text_view); mTextView.setMovementMethod(new ScrollingMovementMethod()); // ... 

使用以下函数将文本附加到TextView。

 private void appendTextAndScroll(String text) { if(mTextView != null){ mTextView.append(text + "\n"); final Layout layout = mTextView.getLayout(); if(layout != null){ int scrollDelta = layout.getLineBottom(mTextView.getLineCount() - 1) - mTextView.getScrollY() - mTextView.getHeight(); if(scrollDelta > 0) mTextView.scrollBy(0, scrollDelta); } } } 

希望这可以帮助。

  scrollview=(ScrollView)findViewById(R.id.scrollview1); tb2.setTextSize(30); tb2=(TextView)findViewById(R.id.textView2); scrollview.fullScroll(View.FOCUS_DOWN); 

或者在TextView中使用这个:

 <TextView android:id="@+id/tb2" android:layout_width="fill_parent" android:layout_height="225sp" android:gravity="top" android:background="@android:drawable/editbox_background" android:scrollbars="vertical"/> 

如果没有scrollTo(),没有ScrollView,没有Runnable,没有gravity =“bottom”,你可以做到这一点,通过执行以下操作:

首先,设置滚动方法:

 mTextView.setMovementMethod(new ScrollingMovementMethod()); 

然后使用以下设置文本:

 SpannableString spannable = new SpannableString(string); Selection.setSelection(spannable, spannable.length()); mTextView.setText(spannable, TextView.BufferType.SPANNABLE); 

setSelection()将光标移动到该索引处。 当TextView设置为SPANNABLE时,它将自动滚动,使光标可见。 请注意,这不会绘制光标,它只是将光标的位置滚动到TextView的可查看部分中。

另外,由于TextView.append()将文本升级为TextView.BufferType.EDITABLE,而可编辑实现了Spannable,所以可以这样做:

 mTextView.append(string); Editable editable = mTextView.getEditableText(); Selection.setSelection(editable, editable.length()); 

我用了一个小窍门…在我的情况下….

 <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_below="@+id/textView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_above="@+id/imageButton"> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/scrollView" android:layout_gravity="left|top" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:inputType="textMultiLine" android:ems="10" android:text="@string/your_text" /> </ScrollView> </FrameLayout> 
 // Layout Views private TextView mConversationView; private ScrollView mConversationViewScroller; use it either in : public void onCreate(Bundle savedInstanceState) { //...blabla setContentView(R.layout.main); //...blablabla mConversationView = (TextView) findViewById(R.id.in); mConversationViewScroller = (ScrollView) findViewById(R.id.scroller); } or in "special" method eg public void initializeChatOrSth(...){ //...blabla mConversationView = (TextView) findViewById(R.id.in); mConversationViewScroller = (ScrollView) findViewById(R.id.scroller); } public void addTextToTextView() { //...blablabla some code byte[] writeBuf = (byte[]) msg.obj; // construct a string from the buffer - i needed this or You can use by"stringing" String writeMessage = new String(writeBuf); mConversationView.append("\n"+"Me: " + writeMessage); mConversationViewScroller.post(new Runnable() { public void run() { mConversationViewScroller.fullScroll(View.FOCUS_DOWN); } }); } this one works fine, also we can maually scroll text to the very top - which is impossible when gravity tag in XML is used. Of course XML (main) the texview should be nested inside scrollview , eg: <ScrollView android:id="@+id/scroller" android:layout_width="match_parent" android:layout_height="280dp" android:fillViewport="true" android:keepScreenOn="true" android:scrollbarStyle="insideInset" android:scrollbars="vertical" > <TextView android:id="@+id/in" android:layout_width="fill_parent" android:layout_height="wrap_content" android:keepScreenOn="true" android:scrollbars="vertical" > </TextView> </ScrollView> 

以避免创build虚拟scroolview我做到了

 int top_scr,rec_text_scrollY; top_scr=(int)rec_text.getTextSize()+rec_text.getHeight(); rec_text_scrollY=rec_text.getLineBounds(rec_text.getLineCount()-1, null)-top_scr; //repeat scroll here and in rec_text.post. //If not scroll here text will be "jump up" after new append, and immediately scroll down //If not scroll in post, than scroll will not be actually processed if(rec_text_scrollY>0)rec_text.scrollTo(0, rec_text_scrollY); rec_text.post(new Runnable(){ @Override public void run() { if(rec_text_scrollY>0)rec_text.scrollTo(0, rec_text_scrollY); } }); 

简单的实现…在您的XML布局定义您的TextView与这些属性:

 <TextView ... android:gravity="bottom" android:scrollbars="vertical" /> 

https://stackoverflow.com/a/7350267/4411645并不完全适合我的工作;

  1. 当文本最近被改变时,getLayout可以抛出NPE。
  2. scrollTo应该改为scrollBy
  3. 它不考虑textview或padding的相对位置。

不用说这是一个很好的起点。 这是我在一个textwatcher的实现的变化。 计算增量时,我们必须从底部减去textView顶部,因为getLineTop()也返回相对于textView顶部的值。

  @Override public void afterTextChanged(Editable editable) { new Handler().postDelayed(new Runnable() { @Override public void run() { Layout layout = textView.getLayout(); if (layout != null) { int lineTop = layout.getLineTop(textView.getLineCount()); final int scrollAmount = lineTop + textView.getPaddingTop() + textView.getPaddingBottom() - textView.getBottom() + textView.getTop(); if (scrollAmount > 0) { textView.scrollBy(0, scrollAmount); } else { textView.scrollTo(0, 0); } } } }, 1000L); } 

你可以玩得更久,以更好地发挥你的智慧。

(2017)使用Kotlin:

 // you need this to enable scrolling: mTextView.movementMethod = ScrollingMovementMethod() // to enable horizontal scrolling, that means word wrapping off: mTextView.setHorizontallyScrolling(true) ... mTextView.text = "Some long long very long text content" mTextView.post { val scrollAmount = mTextView.layout.getLineTop(mTextView.lineCount) - mTextView.height mTextView.scrollTo(0, scrollAmount) } 

这工作文件为我