36

所以,我有一个像这样的 TextView:

<TextView
    android:layout_width="fill_parent"
    android:layout_height="140.7dp"
    android:id="@+id/terminalOutput"
    android:layout_marginBottom="0.0dp"
    android:scrollbars="vertical"
    android:scrollbarAlwaysDrawVerticalTrack="true"
    android:maxLines="8" />

我将它用作一种运行日志,显示给用户,以便他们可以监控大约需要 3 分钟的任务的进度。但是,一旦我超过 8 行,文本就会离开屏幕。这对用户来说是不直观的,因为除了通过尝试向下滚动来手动轮询之外,他们无法知道它离开了屏幕。

我怎样才能做到这样每次我向这个 TextView 添加一些文本时,我都会让它向下滚动到尽可能低的位置?

此外,这是在 Xamarin Android 中,但我认为它不相关。它和Java之间的转换很容易

4

9 回答 9

75

从您的代码中,必须执行两个步骤:

步骤1

虽然你在 Xamarin Android 中编码,但在 Java 中的 xxxActivity.java 中为terminalOutput调用必须是这样的

TextView outputText = (TextView) findViewById(R.id.terminalOutput);
outputText.setMovementMethod(new ScrollingMovementMethod());

通过参数ScrollingMovementMethod()的方法setMovementMethod()就是噱头。

第2步

并且在 Java-Android 中的布局中,同样在 activity_xxx.xml 中的 TextView 声明必须添加这个

android:gravity="bottom"

当您像这样在 outputText 中添加新行时:

outputText.append("\n"+"New text line.");

它会自动滚动到最后一行,这些都是您需要的魔法。

于 2014-07-02T11:55:20.483 回答
35

根据此处的答案在 Android 中使 TextView 可滚动

您实际上不需要使用 ScrollView。

只需设置

android:maxLines = "AN_INTEGER"

android:scrollbars = 布局的 xml 文件中 TextView 的“垂直”属性。

然后使用:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

在你的代码中。

那可行..

于 2013-11-07T03:34:23.493 回答
8

有同样的问题。从这个和类似的讨论中尝试了几个决定,没有任何效果。以这种方式解决它:

edtConsoleText.setSelection(edtConsoleText.getText().length());

在每个.append().

于 2015-07-01T22:32:06.480 回答
8

这些答案都不是我想要的,所以我想出了这个。

textView.append(log);

while (textView.canScrollVertically(1)) {
    textView.scrollBy(0, 10);
}

滚动前不要忘记设置移动方式

textView.setMovementMethod(new ScrollingMovementMethod());
于 2016-06-14T08:16:37.513 回答
5

您可以尝试两种解决方案:

  1. 将 TextView 放入 ScrollView

    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
            <TextView
            android:id="@+id/TextView01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Your Text" >
        </TextView>
    </ScrollView>
    
  2. 使用自定义滚动 TextView(与传统 TextView 相同,但可以滚动)

    import android.content.Context;
    import android.graphics.Rect;
    import android.text.TextPaint;
    import android.util.AttributeSet;
    import android.view.animation.LinearInterpolator;
    import android.widget.Scroller;
    import android.widget.TextView;
    
     public class ScrollTextView extends TextView {
    
    
        // scrolling feature
        private Scroller mSlr;
    
        // milliseconds for a round of scrolling
        private int mRndDuration = 250;
    
        // the X offset when paused
        private int mXPaused = 0;
    
        // whether it's being paused
        private boolean mPaused = true;
    
        /*
         * constructor
         */
        public ScrollTextView(Context context) {
            this(context, null);
            // customize the TextView
            setSingleLine();
            setEllipsize(null);
            setVisibility(INVISIBLE);
        }
    
        /*
         * constructor
         */
        public ScrollTextView(Context context, AttributeSet attrs) {
            this(context, attrs, android.R.attr.textViewStyle);
            // customize the TextView
            setSingleLine();
            setEllipsize(null);
            setVisibility(INVISIBLE);
        }
    
        /*
         * constructor
         */
        public ScrollTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            // customize the TextView
            setSingleLine();
            setEllipsize(null);
            setVisibility(INVISIBLE);
        }
    
        /**
         * begin to scroll the text from the original position
         */
        public void startScroll() {
            // begin from the very right side
            mXPaused = -1 * getWidth();
            // assume it's paused
            mPaused = true;
            resumeScroll();
        }
    
        /**
         * resume the scroll from the pausing point
         */
        public void resumeScroll() {
    
            if (!mPaused)
                return;
    
            // Do not know why it would not scroll sometimes
            // if setHorizontallyScrolling is called in constructor.
            setHorizontallyScrolling(true);
    
            // use LinearInterpolator for steady scrolling
            mSlr = new Scroller(this.getContext(), new LinearInterpolator());
            setScroller(mSlr);
    
            int scrollingLen = calculateScrollingLen();
            int distance = scrollingLen - (getWidth() + mXPaused);
            int duration = (new Double(mRndDuration * distance * 1.00000
                    / scrollingLen)).intValue();
    
            setVisibility(VISIBLE);
            mSlr.startScroll(mXPaused, 0, distance, 0, duration);
            mPaused = false;
        }
    
        /**
         * calculate the scrolling length of the text in pixel
         * 
         * @return the scrolling length in pixels
         */
        private int calculateScrollingLen() {
            TextPaint tp = getPaint();
            Rect rect = new Rect();
            String strTxt = getText().toString();
            tp.getTextBounds(strTxt, 0, strTxt.length(), rect);
            int scrollingLen = rect.width() + getWidth();
            rect = null;
            return scrollingLen;
        }
    
        /**
         * pause scrolling the text
         */
        public void pauseScroll() {
            if (null == mSlr)
                return;
    
            if (mPaused)
                return;
    
            mPaused = true;
    
            // abortAnimation sets the current X to be the final X,
            // and sets isFinished to be true
            // so current position shall be saved
            mXPaused = mSlr.getCurrX();
    
            mSlr.abortAnimation();
        }
    
        @Override
        /*
         * override the computeScroll to restart scrolling when finished so as that
         * the text is scrolled forever
         */
        public void computeScroll() {
            super.computeScroll();
    
            if (null == mSlr)
                return;
    
            if (mSlr.isFinished() && (!mPaused)) {
                this.startScroll();
            }
        }
    
        public int getRndDuration() {
            return mRndDuration;
        }
    
        public void setRndDuration(int duration) {
            this.mRndDuration = duration;
        }
    
        public boolean isPaused() {
            return mPaused;
        }
     }
    

如何使用:

ScrollTextView scrolltext = (ScrollTextView) findViewById(R.id.YourTextView);

(ScrollTextView类源:http ://bear-polka.blogspot.com/2009/01/scrolltextview-scrolling-textview-for.html )

于 2013-11-07T02:46:29.340 回答
4

来自“如何在活动启动时在 ScrollView 中滚动到底部”:

final ScrollView scrollview = ((ScrollView) findViewById(R.id.scrollview));
scrollview.post(new Runnable() {
  @Override
  public void run() {
    scrollview.fullScroll(ScrollView.FOCUS_DOWN);
  }
});

您需要的是fullScroll()在附加操作之后放置。

于 2015-02-09T05:23:08.783 回答
2

我正在使用 Xmarin。

我的解决方案和很多人提到的一样,在 ScrollView 中使用 textView。

如果您想在视图底部看到新行,请使用

android:layout_gravity="bottom"

这会将新行保持在底部,直到您滚动视图。无论您滚动到哪里,该视图都会保持不变。

不需要代码。

但是,如果您希望追加后内容始终位于底部,则需要在 append() 之后添加代码:

myText.Append(...);

myscroll.FullScroll(FocusSearchDirection.Down);
于 2016-11-10T20:47:31.503 回答
0

对我来说,除了这两者的结合之外,没有什么能完美地工作:-

  • 在你的java类中设置scroller.scrollTo(0, 70); 。在设置你的textview之前使用它,但在附加该字符串之后。52 dp 是我设备的高度。您可以使用 scroller.getBottom()) 找到它;所以我用 70 来调整滚动视图。
  • 在你的文本视图中设置android:scrollY="30dp"
于 2018-06-01T07:05:11.613 回答
0

就我而言,起初没有任何效果,因为我显然试图在 UI 线程之外对 UI 进行更改(添加看不见的文本后自动向上滚动)。文字会显示,但不会自动滚动。更正, setText 可以工作但不能追加。

我对自动滚动的调用不在 UI 线程中,因为我编写了响应套接字 onMessage 调用的调用;我在自己的线程上运行。所以,我不得不用下面的代码附上我的函数调用,一切正常。

 runOnUiThread(new Runnable() {
                 @Override
                 public void run() {

                     // Stuff that updates the UI

                 }
             });

我敢肯定,只要您在 UI 线程上运行所有方法,所有方法都会以某种方式工作。但是,为了实现“聊天室”的自动滚动效果,即聊天窗口顶部的新文本,但当文本量比窗口长时 - 将新消息自动滚动到视图中,我只是使用了 ... fullScroll(View .FOCUS_DOWN) ... 方法。

于 2020-02-18T15:56:07.343 回答