在android中自动滚动TextView以将文本带入视野

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3506696/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 10:31:27  来源:igfitidea点击:

auto-scrolling TextView in android to bring text into view

androidscrolltextview

提问by Kyle

I have a TextViewthat I'm dynamically adding text to.

我有一个TextView我正在向其中动态添加文本的内容。

in my main.xmlfile I have the properties set to make my max lines 19 and scrollbars vertical.

在我的main.xml文件中,我将属性设置为使我的最大行数为 19 并且滚动条垂直。

in the .javafile I am using textview.setMovementMethod(new ScrollingMovementMethod());to allow for scrolling.

.javatextview.setMovementMethod(new ScrollingMovementMethod());用来允许滚动的文件中。

The scrolling works great. As soon as 19 lines are taken up, and more lines are added it starts scrolling just as it should. The problem is, I want the new text to scroll into view.

滚动效果很好。一旦占用了 19 行,并且添加了更多行,它就会开始按原样滚动。问题是,我希望新文本滚动到视图中。

I am writing out the value for textview.getScrollY()and it stays at 0no matter what (even if I manually scroll it down and add a new line of text).

我正在写出它的值textview.getScrollY()并且0无论如何它都保持不变(即使我手动向下滚动它并添加新的文本行)。

consequently textview.scrollTo(0, textview.getScrollY());does nothing for me.

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

Is there another method I should be using to obtain the vertical scroll amount for the textview? Everything I've read says that for all intents and purposes, what I'm doing should be working :/

我应该使用另一种方法来获取 的垂直滚动量textview吗?我读过的所有内容都表明,出于所有意图和目的,我正在做的事情应该有效:/

回答by KNfLrPn

Took some digging through the TextView source but here's what I came up with. It doesn't require you to wrap the TextView in a ScrollView and, as far as I can tell, works perfectly.

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

Please let me know if you find a case where this fails. I'd appreciate being able to fix any bugs in my app ;)

如果您发现失败的情况,请告诉我。我很高兴能够修复我的应用程序中的任何错误;)

Edit: I should mention that I also use

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

mTextView.setMovementMethod(new ScrollingMovementMethod());

after instantiating my TextView.

在实例化我的 TextView 之后。

回答by Bryce Thomas

Use android:gravity="bottom"on the TextView in your XML layout. E.g.

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

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

Don't ask me why it works.

不要问我为什么有效。

The only problem with this method is if you want to then scroll back up the textview, it keeps getting "pulled down" to the bottom again each time new text is inserted.

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

回答by Someone Somewhere

this is what I use to scroll all the way to the bottom of my chat text ...

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

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

EDIT: here's the XML layout

编辑:这是 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>

回答by user1230812

Previous answers did not work correctly for me, this however works.

以前的答案对我来说不起作用,但这有效。

Create a TextView and do the following:

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

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

Use the following function to append text to the TextView.

使用以下函数将文本附加到 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);
        }
    }
}

Hope this helps.

希望这可以帮助。

回答by tsmigiel

TextView already has auto-scrolling if you set the text using Spannable or Editable strings with the cursor position set in them.

如果您使用 Spannable 或 Editable 字符串设置文本并在其中设置光标位置,则 TextView 已经具有自动滚动功能。

First, set the scrolling method:

首先,设置滚动方式:

mTextView.setMovementMethod(new ScrollingMovementMethod());

Then use the following to set the text:

然后使用以下内容设置文本:

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

The setSelection() moves the cursor to that index. When a TextView is set to a SPANNABLE it will automatically scroll to make the cursor visible. Note that this does not draw the cursor, it just scrolls the location of the cursor to be in the viewable section of the TextView.

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

Also, since TextView.append() upgrades the text to TextView.BufferType.EDITABLE and Editable implements Spannable, you can do this:

此外,由于 TextView.append() 将文本升级为 TextView.BufferType.EDITABLE 并且 Editable 实现了 Spannable,您可以这样做:

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

Here is a full widget implementation. Simply call setText() or append() on this widget. It's slightly different than above because it extends from EditText which already forces its internal text to be Editable.

这是一个完整的小部件实现。只需在此小部件上调用 setText() 或 append() 即可。它与上面的略有不同,因为它从 EditText 扩展,它已经强制其内部文本为可编辑。

import android.content.Context;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.MovementMethod;
import android.text.method.ScrollingMovementMethod;
import android.text.method.Touch;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;

public class AutoScrollTextView extends AppCompatEditText {
    public AutoScrollTextView(Context context) {
        this(context, null);
    }

    public AutoScrollTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AutoScrollTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected boolean getDefaultEditable() {
        return false;
    }

    @Override
    protected MovementMethod getDefaultMovementMethod() {
        return new CursorScrollingMovementMethod();
    }

    @Override
    public void setText(CharSequence text, BufferType type) {
        super.setText(text, type);
        scrollToEnd();
    }

    @Override
    public void append(CharSequence text, int start, int end) {
        super.append(text, start, end);
        scrollToEnd();
    }

    public void scrollToEnd() {
        Editable editable = getText();
        Selection.setSelection(editable, editable.length());
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        event.setClassName(AutoScrollTextView.class.getName());
    }

    /**
     * Moves cursor when scrolled so it doesn't auto-scroll on configuration changes.
     */
    private class CursorScrollingMovementMethod extends ScrollingMovementMethod {

        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            widget.moveCursorToVisibleOffset();
            return super.onTouchEvent(widget, buffer, event);
        }
    }
}

回答by Almaz

(2017) using Kotlin:

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

This works file for me

这对我有用

回答by Amitsharma

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

Or use this in TextView:

或者在 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"/>

回答by Stephan

I used a little trick ... in my case....

我使用了一个小技巧......就我而言......

<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>

回答by noelicus

Simple implementation...in your XML layout define your TextView with these attributes:

简单的实现...在您的 XML 布局中使用以下属性定义您的 TextView:

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

回答by Maciek

// 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 e.g. 

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 , e.g:

<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>