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

Kyl*_*yle 47 android scroll textview

我有一个TextView我正在动态添加文本.

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

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

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

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

因此textview.scrollTo(0, textview.getScrollY());对我没有任何作用.

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

KNf*_*rPn 72

通过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);
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:我应该提一下我也用

mTextView.setMovementMethod(new ScrollingMovementMethod());
Run Code Online (Sandbox Code Playgroud)

在实例化我的TextView之后.

  • 这是一个很好的建议,谢谢!但是,它并不像您发布的那样完全正常,因为如果最近更改了文本,`TextView.getLayout()`可以返回null.与其他答案一样,解决方案是将整个滚动量计算和`scrollTo()`调用放入`mTextView.post(new Runnable(){...`call. (16认同)
  • 我只是为.getlayout添加了一个空检查.它工作正常 (2认同)

Bry*_*mas 54

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

<TextView
    ...
    android:gravity="bottom"
    ...
/>
Run Code Online (Sandbox Code Playgroud)

不要问我为什么会这样.

此方法的唯一问题是,如果您想要向后滚动文本视图,每次插入新文本时它都会再次"拉下"到底部.

  • 对于我想要的,只是信息在TextView的底部不断转储,这是迄今为止最好的选择.令人惊讶的是,有时候错过简单的选项是多么容易.谢谢. (2认同)
  • 它工作正常,但在超过定义的大小时不显示可滚动条。如果您还想使用条形符号滚动视图,请在定义的 xml 中添加 android:scrollbars="vertical/horizo​​ntal"。 (2认同)
  • 不适用于android.support.v4.widget.NestedScrollView内的TextView。 (2认同)
  • 我对这种方法的问题是它看起来很奇怪 ** 在 `TextView` 填满之前**,因为所有文本都位于底部。我还没有找到解决方法,但在“连续记录”的情况下,“TextView”首先从顶部填充,但在填充后不断滚动到底部,这对我来说似乎更自然。我想这是否会困扰人们取决于它填满的速度和频率。 (2认同)

Som*_*ere 28

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

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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是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>
Run Code Online (Sandbox Code Playgroud)

  • @Someone - 但是OP没有使用ScrollView - op正在使用TextView w滚动==>"textview.setMovementMethod(new ScrollingMovementMethod());以允许滚动." (2认同)

小智 22

以前的答案对我来说无法正常工作,但这有效.

创建TextView并执行以下操作:

// ...
mTextView = (TextView)findViewById(R.id.your_text_view);
mTextView.setMovementMethod(new ScrollingMovementMethod());
// ...
Run Code Online (Sandbox Code Playgroud)

使用以下函数将文本追加到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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.


tsm*_*iel 8

如果使用设置了光标位置的Spannable或Editable字符串设置文本,TextView已经自动滚动.

首先,设置滚动方法:

mTextView.setMovementMethod(new ScrollingMovementMethod());
Run Code Online (Sandbox Code Playgroud)

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

SpannableString spannable = new SpannableString(string);
Selection.setSelection(spannable, spannable.length());
mTextView.setText(spannable, TextView.BufferType.SPANNABLE);
Run Code Online (Sandbox Code Playgroud)

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

此外,由于TextView.append()将文本升级为TextView.BufferType.EDITABLE而Editable实现了Spannable,因此您可以执行以下操作:

mTextView.append(string);
Editable editable = mTextView.getEditableText();
Selection.setSelection(editable, editable.length());
Run Code Online (Sandbox Code Playgroud)

这是一个完整的小部件实现.只需在此小部件上调用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案!其他解决方案似乎效果不佳或并非一直有效等。 (3认同)

Alm*_*maz 5

(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)
}
Run Code Online (Sandbox Code Playgroud)

这对我有用