简体   繁体   English

使 TextView 可在 Android 上滚动

[英]Making TextView scrollable on Android

I am displaying text in a TextView that appears to be too long to fit into one screen.我在 TextView 中显示文本,该文本似乎太长而无法放入一个屏幕。 I need to make my TextView scrollable.我需要使我的 TextView 可滚动。 How can I do that?我怎样才能做到这一点?

Here is the code:这是代码:

final TextView tv = new TextView(this);
tv.setBackgroundResource(R.drawable.splash);
tv.setTypeface(face);
tv.setTextSize(18);
tv.setTextColor(R.color.BROWN);
tv.setGravity(Gravity.CENTER_VERTICAL| Gravity.CENTER_HORIZONTAL);
tv.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent e) {
        Random r = new Random();
        int i = r.nextInt(101);
        if (e.getAction() == e.ACTION_DOWN) {
            tv.setText(tips[i]);
            tv.setBackgroundResource(R.drawable.inner);
        }
        return true;
    }
});
setContentView(tv);

You don't need to use a ScrollView actually.您实际上不需要使用ScrollView

Just set the只需设置

android:scrollbars = "vertical"

properties of your TextView in your layout's xml file.布局的 xml 文件中TextView属性。

Then use:然后使用:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

in your code.在你的代码中。

Bingo, it scrolls!宾果游戏,它滚动!

This is how I did it purely in XML:这就是我纯粹在 XML 中所做的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ScrollView
        android:id="@+id/SCROLLER_ID"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:scrollbars="vertical"
        android:fillViewport="true">

        <TextView
            android:id="@+id/TEXT_STATUS_ID"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1.0"/>
    </ScrollView>
</LinearLayout>

NOTES:笔记:

  1. android:fillViewport="true" combined with android:layout_weight="1.0" will make the textview take up all available space. android:fillViewport="true"结合android:layout_weight="1.0"将使 textview 占用所有可用空间。

  2. When defining the Scrollview, DO NOT specify android:layout_height="fill_parent" otherwise the scrollview doesn't work!定义滚动视图时,请勿指定android:layout_height="fill_parent"否则滚动视图不起作用! (this has caused me to waste an hour just now! FFS). (这让我刚才浪费了一个小时!FFS)。

PRO TIP:专家提示:

To programmatically scroll to the bottom after appending text, use this:要在附加文本后以编程方式滚动到底部,请使用以下命令:

mTextStatus = (TextView) findViewById(R.id.TEXT_STATUS_ID);
mScrollView = (ScrollView) findViewById(R.id.SCROLLER_ID);

private void scrollToBottom()
{
    mScrollView.post(new Runnable()
    {
        public void run()
        {
            mScrollView.smoothScrollTo(0, mTextStatus.getBottom());
        }
    });
}

All that is really necessary is the setMovementMethod().真正需要的是 setMovementMethod()。 Here's an example using a LinearLayout.这是使用 LinearLayout 的示例。

File main.xml文件main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:id="@+id/tv1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:text="@string/hello"
    />
</LinearLayout>

File WordExtractTest.java文件WordExtractTest.java

public class WordExtractTest extends Activity {

    TextView tv1;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        tv1 = (TextView)findViewById(R.id.tv1);

        loadDoc();
    }

    private void loadDoc() {

        String s = "";

        for(int x=0; x<=100; x++) {
            s += "Line: " + String.valueOf(x) + "\n";
        }

        tv1.setMovementMethod(new ScrollingMovementMethod());

        tv1.setText(s);
    }
}

Make your textview just adding this让你的 textview 只添加这个

TextView textview= (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(new ScrollingMovementMethod());

It is not necessary to put in没有必要放入

android:Maxlines="AN_INTEGER"`

You can do your work by simply adding:您只需添加以下内容即可完成您的工作:

android:scrollbars = "vertical"

And, put this code in your Java class:并且,将此代码放在您的 Java 类中:

textview.setMovementMethod(new ScrollingMovementMethod());

You can either你可以

  1. surround the TextView by a ScrollView ;ScrollView包围TextView or或者
  2. set the Movement method to ScrollingMovementMethod.getInstance();将移动方法设置为ScrollingMovementMethod.getInstance(); . .

The best way I found:我发现的最好方法:

Replace the TextView with an EditText with these extra attributes:用带有这些额外属性的 EditText 替换 TextView:

android:background="@null"
android:editable="false"
android:cursorVisible="false"

There is no need for wrapping in a ScrollView.不需要包装在 ScrollView 中。

Simple.简单的。 This is how I did it:我是这样做的:

  1. XML Side: XML 端:

     <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" tools:context="com.mbh.usbcom.MainActivity"> <TextView android:id="@+id/tv_log" android:layout_width="match_parent" android:layout_height="wrap_content" android:scrollbars="vertical" android:text="Log:" /> </RelativeLayout>
  2. Java side: Java端:

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

Bonus:奖金:

To let the text view scroll down as the text fill it, you have to add:要让文本视图在文本填充时向下滚动,您必须添加:

    android:gravity="bottom"

to the TextView xml file.到 TextView xml 文件。 It will scroll down automatically as more text comes in.随着更多文本进入,它会自动向下滚动。

Of course you need to add the text using the append function instead of set text:当然,您需要使用 append 函数而不是 set text 添加文本:

    tv_log.append("\n" + text);

I used it for Log purpose.我将它用于日志目的。

I hope this helps ;)我希望这有帮助 ;)

This is "How to apply ScrollBar to your TextView", using only XML.这是“如何将 ScrollBar 应用到您的 TextView”,仅使用 XML。

First, you need to take a Textview control in the main.xml file and write some text into it ... like this:首先,您需要在main.xml文件中获取一个 Textview 控件并在其中写入一些文本......像这样:

<TextView
    android:id="@+id/TEXT"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="@string/long_text"/>

Next, place the text view control in between the scrollview to display the scroll bar for this text:接下来,将文本视图控件放在滚动视图之间以显示此文本的滚动条:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent">

    <ScrollView
        android:id="@+id/ScrollView01"
        android:layout_height="150px"
        android:layout_width="fill_parent">

        <TextView
            android:id="@+id/TEXT"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:text="@string/long_text"/>

    </ScrollView>
</RelativeLayout>

That's it...就是这样...

This will provide smooth scrolling text with a scroll bar.这将提供带有滚动条的平滑滚动文本。

ScrollView scroller = new ScrollView(this);
TextView tv = new TextView(this);
tv.setText(R.string.my_text);
scroller.addView(tv);

The "pro tip" above from Someone Somewhere ( Making TextView scrollable on Android ) works great, however, what if you're dynamically adding text to the ScrollView and would like to automatically scroll to the bottom after an append only when the user is at the bottom of the ScrollView?上面来自有人某处的“专业提示”( 使 TextView 在 Android 上可滚动)效果很好,但是,如果您动态地将文本添加到 ScrollView 并且希望在用户在附加后自动滚动到底部,该怎么办ScrollView 的底部? (Perhaps because if the user has scrolled up to read something you don't want to automatically reset to the bottom during an append, which would be annoying.) (也许是因为如果用户向上滚动阅读某些内容,您不想在追加期间自动重置到底部,这会很烦人。)

Anyway, here it is:无论如何,这里是:

if ((mTextStatus.getMeasuredHeight() - mScrollView.getScrollY()) <=
        (mScrollView.getHeight() + mTextStatus.getLineHeight())) {
    scrollToBottom();
}

The mTextStatus.getLineHeight() will make it so that you don't scrollToBottom() if the user is within one line from the end of the ScrollView. mTextStatus.getLineHeight() 将使您不会在用户位于 ScrollView 末尾的一行内时使用 scrollToBottom()。

If you want text to be scrolled within the textview, then you can follow the following:如果要在 textview 中滚动文本,则可以按照以下操作:

First you should have to subclass textview.首先,您必须对 textview 进行子类化。

And then use that.然后使用它。

Following is an example of a subclassed textview.以下是子类文本视图的示例。

public class AutoScrollableTextView extends TextView {

    public AutoScrollableTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setEllipsize(TruncateAt.MARQUEE);
        setMarqueeRepeatLimit(-1);
        setSingleLine();
        setHorizontallyScrolling(true);
    }

    public AutoScrollableTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setEllipsize(TruncateAt.MARQUEE);
        setMarqueeRepeatLimit(-1);
        setSingleLine();
        setHorizontallyScrolling(true);
    }

    public AutoScrollableTextView(Context context) {
        super(context);
        setEllipsize(TruncateAt.MARQUEE);
        setMarqueeRepeatLimit(-1);
        setSingleLine();
        setHorizontallyScrolling(true);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        if(focused)
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
    }

    @Override
    public void onWindowFocusChanged(boolean focused) {
        if(focused)
            super.onWindowFocusChanged(focused);
    }

    @Override
    public boolean isFocused() {
        return true;
    }
}

Now, you have to use that in the XML in this way:现在,您必须以这种方式在 XML 中使用它:

 <com.yourpackagename.AutoScrollableTextView
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="This is very very long text to be scrolled"
 />

That's it.就是这样。

Add the following in the textview in XML.在 XML 中的文本视图中添加以下内容。

android:scrollbars="vertical"

And finally, add最后,添加

textView.setMovementMethod(new ScrollingMovementMethod());

in the Java file.在 Java 文件中。

In kotlin for making the textview scrollable在 kotlin 中使 textview 可滚动

myTextView.movementMethod= ScrollingMovementMethod()

and also add in xml this property并在xml中添加此属性

    android:scrollbars = "vertical"

I didn't find TextView scrolling to support the 'fling' gesture, where it continues scrolling after a flick up or down.我没有发现 TextView 滚动支持“fling”手势,它在向上或向下滑动后继续滚动。 I ended up implementing that myself because I didn't want to use a ScrollView for various reasons, and there didn't seem to be a MovementMethod that both allowed me to select text and click on links.我最终自己实现了它,因为出于各种原因我不想使用 ScrollView,而且似乎没有一个 MovementMethod 允许我选择文本和单击链接。

完成可滚动后,当您在视图中输入任何内容时,将此行添加到视图的最后一行:

((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);

If you don't want to use the EditText solution then you might have better luck with:如果您不想使用 EditText 解决方案,那么您可能会有更好的运气:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.yourLayout);
    (TextView)findViewById(R.id.yourTextViewId).setMovementMethod(ArrowKeyMovementMethod.getInstance());
}

Add this to your XML layout:将此添加到您的 XML 布局:

android:ellipsize="marquee"
android:focusable="false"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:text="To Make An textView Scrollable Inside The TextView Using Marquee"

And in code you have to write the following lines:在代码中,您必须编写以下几行:

textview.setSelected(true);
textView.setMovementMethod(new ScrollingMovementMethod());

The code below creates an automatic horizontal scrolling textview:下面的代码创建了一个自动水平滚动的文本视图:

While adding TextView to xml use将 TextView 添加到 xml 时使用

<TextView android:maxLines="1" 
          android:ellipsize="marquee"
          android:scrollHorizontally="true"/>

Set the following properties of TextView in onCreate()在 onCreate() 中设置 TextView 的以下属性

tv.setSelected(true);
tv.setHorizontallyScrolling(true); 

I had this problem when I was using TextView inside the ScrollView .我在ScrollView使用TextView时遇到了这个问题。 This solution has worked for me.这个解决方案对我有用。

scrollView.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                description.getParent().requestDisallowInterceptTouchEvent(false);

                return false;
            }
        });

        description.setOnTouchListener(new View.OnTouchListener() {

            @Override
            public boolean onTouch(View v, MotionEvent event) {

                description.getParent().requestDisallowInterceptTouchEvent(true);

                return false;
            }
        });
yourtextView.setMovementMethod(new ScrollingMovementMethod());

你现在可以滚动它。

Use it like this像这样使用它

<TextView  
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:maxLines = "AN_INTEGER"
    android:scrollbars = "vertical"
/>

Put maxLines and scrollbars inside TextView in xml.maxLinesscrollbars放在 xml 中的 TextView 中。

<TextView android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:scrollbars="vertical"
    android:maxLines="5" // any number of max line here.
    />

Then in java code.然后在java代码中。

textView.setMovementMethod(new ScrollingMovementMethod());

whenever you need to use the ScrollView as parent , And you also use the scroll movement method with TextView.每当您需要使用 ScrollView 作为 parent 时,您还可以使用 TextView 的滚动移动方法。

And When you portrait to landscape your device that time occur some issue .并且当您将设备纵向横向放置时会出现一些问题 (like) entire page is scrollable but scroll movement method can't work. (例如)整个页面可滚动但滚动移动方法无法工作。

if you still need to use ScrollView as parent or scroll movement method then you also use below desc.如果您仍然需要使用 ScrollView 作为父级或滚动移动方法,那么您也可以使用下面的说明。

If you do not have any problems then you use EditText instead of TextView如果您没有任何问题,则使用 E​​ditText 而不是 TextView

see below :见下文 :

<EditText
     android:id="@+id/description_text_question"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:background="@null"
     android:editable="false"
     android:cursorVisible="false"
     android:maxLines="6"/>

Here, the EditText behaves like TextView在这里, EditText 的行为类似于 TextView

And your issue will be resolved您的问题将得到解决

If you use Kotlin , in this way : XML如果你使用Kotlin ,这样: XML

 <TextView
            android:id="@+id/tvMore"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:maxLines="3"
            android:scrollbars="vertical" />

Activity活动

tvMore.movementMethod = ScrollingMovementMethod()

I know this is an older post, but this is how I am handling the issue on the Java side.我知道这是一篇较旧的帖子,但这就是我在 Java 方面处理问题的方式。

    // Allow textView to scroll
    tv.setSingleLine(true);
    tv.setHorizontallyScrolling(true);
    tv.setEllipsize(TextUtils.TruncateAt.MARQUEE);
    tv.setMarqueeRepeatLimit(-1); // Infinite
    // TextView must be 'selected'
    tv.setSelected(true);
    // Padding not necessary, but this helps so the text isn't right
    // up against the side of a screen/layout
    tv.setPadding(10, 0, 10, 0);

Here is the answer in the wonderful and happy world of JetPack Compose:在 JetPack Compose 精彩而快乐的世界里,答案在这里:

LazyColumn {
        item {
            Text(
                text = "My Long Text"
            )
        }
    }

I struggled with this for over a week and finally figured out how to make this work!我为此苦苦挣扎了一个多星期,终于想出了如何使这项工作发挥作用!

My issue was that everything would scroll as a 'block'.我的问题是一切都会作为“块”滚动。 The text itself was scrolling, but as a chunk rather than line by line.文本本身正在滚动,但作为一个块而不是一行一行。 This obviously didn't work for me, because it would cut off lines at the bottom.这显然对我不起作用,因为它会切断底部的线条。 All of the previous solutions did not work for me, so I crafted my own.以前的所有解决方案都不适用于我,所以我自己制作了。

Here is the easiest solution by far:这是迄今为止最简单的解决方案:

Make a class file called: 'PerfectScrollableTextView' inside a package, then copy and paste this code in:在包中创建一个名为“PerfectScrollableTextView”的类文件,然后将此代码复制并粘贴到:

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;

public class PerfectScrollableTextView extends TextView {

    public PerfectScrollableTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setVerticalScrollBarEnabled(true);
        setHorizontallyScrolling(false);
    }

    public PerfectScrollableTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setVerticalScrollBarEnabled(true);
        setHorizontallyScrolling(false);
    }

    public PerfectScrollableTextView(Context context) {
        super(context);
        setVerticalScrollBarEnabled(true);
        setHorizontallyScrolling(false);
    }

    @Override
    protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
        if(focused)
            super.onFocusChanged(focused, direction, previouslyFocusedRect);
    }

    @Override
    public void onWindowFocusChanged(boolean focused) {
        if(focused)
            super.onWindowFocusChanged(focused);
    }

    @Override
    public boolean isFocused() {
        return true;
    }
}

Finally change your 'TextView' in XML:最后在 XML 中更改您的“TextView”:

From: <TextView来自: <TextView

To: <com.your_app_goes_here.PerfectScrollableTextView至: <com.your_app_goes_here.PerfectScrollableTextView

In my case.Constraint Layout.AS 2.3.在我的情况下。约束布局。AS 2.3。

Code implementation:代码实现:

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML: XML:

android:scrollbars="vertical"
android:scrollIndicators="right|end"

XML - You can use android:scrollHorizontally Attribute XML - 您可以使用android:scrollHorizontally属性

Whether the text is allowed to be wider than the view (and therefore can be scrolled horizontally).是否允许文本比视图更宽(因此可以水平滚动)。

May be a boolean value, such as "true" or "false".可能是布尔值,例如“true”或“false”。

Prigramacaly - setHorizontallyScrolling(boolean) Prigramacaly - setHorizontallyScrolling(boolean)

尝试这个:

android:scrollbars = "vertical"

For a vertically or horizontally scrollable TextView some of the other answers help, but I needed to be able to scroll both ways.对于垂直水平滚动的 TextView,其他一些答案有帮助,但我需要能够双向滚动。

What finally worked is a ScrollView with a HorizontalScrollView inside of it, and a TextView inside the HSV.最终起作用的是一个 ScrollView,里面有一个 Horizo​​ntalScrollView,一个 TextView 在 HSV 里面。 It's very smooth and can easily go side to side or top to bottom in one swipe.它非常光滑,一次滑动即可轻松地左右移动或从上到下移动。 It also only allows scrolling in one direction at a time so there's none of the jumping side to side while scrolling up or down.它还一次只允许向一个方向滚动,因此在向上或向下滚动时不会左右跳跃。

An EditText with editing and cursor disabled works, but it feels terrible.禁用编辑和光标的 EditText 可以工作,但感觉很糟糕。 Each attempt to scroll moves the cursor and it requires many swipes to go top to bottom or side to side in even a ~100-line file.每次尝试滚动都会移动光标,即使在大约 100 行的文件中,它也需要多次滑动才能从上到下或左右滑动。

Using setHorizontallyScrolling(true) can work, but there's no similar method to allow vertical scrolling, and it doesn't work inside of a ScrollView as far as I can tell (just learning though, could be wrong).使用setHorizontallyScrolling(true)可以工作,但没有类似的方法来允许垂直滚动,据我所知,它在 ScrollView 内不起作用(尽管只是学习,可能是错误的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM