Делаем TextView прокручиваемым на Android

Я отображаю текст в текстовом представлении, которое кажется слишком длинным, чтобы поместиться на одном экране. Мне нужно сделать мой TextView прокручиваемым. Как я могу это сделать?

Вот код:

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

32 ответа

Решение

Вам не нужно использовать ScrollView на самом деле.

Просто установите

android:scrollbars = "vertical"

свойства вашего TextView в XML-файле вашего макета.

Тогда используйте:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

в вашем коде.

Бинго, это свитки!

Вот как я сделал это чисто в 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>

ЗАМЕТКИ:

  1. android:fillViewport="true" в сочетании с android:layout_weight="1.0" заставит textview занять все доступное пространство.

  2. При определении Scrollview НЕ указывайте android:layout_height="fill_parent" в противном случае прокрутка не работает! (это заставило меня потратить впустую час только сейчас! FFS).

PRO TIP:

Чтобы программно прокрутить до конца после добавления текста, используйте это:

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

Все, что действительно необходимо, это setMovementMethod(). Вот пример использования LinearLayout.

Файл 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>

Файл 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);
    }
}

Сделайте свое текстовое представление просто добавив это

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

Не нужно ставить в

android:Maxlines="AN_INTEGER"`

Вы можете сделать свою работу, просто добавив:

android:scrollbars = "vertical"

И поместите этот код в ваш класс Java:

textview.setMovementMethod(new ScrollingMovementMethod());

Лучший способ, который я нашел:

Замените TextView на EditText с этими дополнительными атрибутами:

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

Нет необходимости в переносе в ScrollView.

Вы также можете

  1. окружить TextView по ScrollView; или же
  2. установите метод Movement в ScrollingMovementMethod.getInstance();,

Просто. Вот как я это сделал:

  1. Сторона 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 сторона:

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

Бонус:

Чтобы текстовое представление прокручивалось вниз по мере заполнения текста, вы должны добавить:

    android:gravity="bottom"

в текстовый XML-файл. Он будет прокручиваться автоматически по мере поступления текста.

Конечно, вам нужно добавить текст, используя функцию добавления вместо набора текста:

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

Я использовал это для целей журнала.

Надеюсь, это поможет;)

Если вы используете Kotlin , таким образом:XML

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

Мероприятия

      tvMore.movementMethod = ScrollingMovementMethod()

Это "Как применить ScrollBar к вашему TextView", используя только XML.

Во-первых, вам нужно взять элемент управления Textview в файле main.xml и записать в него некоторый текст... вот так:

<TextView
    android:id="@+id/TEXT"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="@string/long_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>

Это оно...

В kotlin для прокрутки текста

myTextView.movementMethod= ScrollingMovementMethod()

а также добавить в XML это свойство

    android:scrollbars = "vertical"

Приведенный выше "совет" от Someone Somewhere (настройка прокрутки TextView на Android) прекрасно работает, однако, что делать, если вы динамически добавляете текст в ScrollView и хотели бы автоматически прокручиваться вниз после добавления только тогда, когда пользователь находится в нижняя часть ScrollView? (Возможно, потому что, если пользователь прокрутил что-то, чтобы прочитать что-то, вы не хотите автоматически сбрасывать его во время добавления, что будет раздражать.)

Во всяком случае, вот оно:

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

MTextStatus.getLineHeight() сделает так, чтобы вы не использовали scrollToBottom(), если пользователь находится в пределах одной строки от конца ScrollView.

Это обеспечит плавную прокрутку текста с помощью полосы прокрутки.

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

Если вы хотите, чтобы текст прокручивался в текстовом представлении, вы можете выполнить следующие действия:

Сначала вы должны создать подкласс 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;
    }
}

Теперь вы должны использовать это в 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"
 />

Вот и все.

Добавьте следующее в текстовое представление в XML.

android:scrollbars="vertical"

И, наконец, добавить

textView.setMovementMethod(new ScrollingMovementMethod());

в файле Java.

yourtextView.setMovementMethod(new ScrollingMovementMethod());

вы можете прокрутить его сейчас.

Я не нашел прокрутки TextView для поддержки жеста "броска", когда он продолжает прокручиваться после пролистывания вверх или вниз. Я сам реализовал это, потому что не хотел использовать ScrollView по разным причинам, и, похоже, не было MovementMethod, который позволял бы мне выделять текст и нажимать на ссылки.

Когда вы закончите с прокруткой, добавьте эту строку в последнюю строку представления, когда вы вводите что-либо в представление:

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

Добавьте это к вашему 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"

И в коде вы должны написать следующие строки:

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

Если вы не хотите использовать решение EditText, то вам может повезти с:

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

Я знаю, что это более старый пост, но именно так я решаю проблему на стороне 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);

У меня была эта проблема, когда я использовал TextView внутри ScrollView, Это решение сработало для меня.

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

Код ниже создает автоматическую горизонтальную прокрутку текста:

При добавлении TextView для использования XML

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

Установите следующие свойства TextView в onCreate()

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

Всякий раз, когда вам нужно использовать ScrollView в качестве родителя, а также вы используете метод перемещения прокрутки с TextView.

А при портретной ориентации вашего устройства в это время возникают некоторые проблемы. (например) вся страница прокручивается, но метод перемещения прокрутки не может работать.

если вам все еще нужно использовать ScrollView в качестве родительского или метода прокрутки, то вы также используете ниже desc.

Если у вас нет никаких проблем, тогда вы используете EditText вместо TextView

увидеть ниже:

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

Здесь EditText ведет себя как TextView

И ваша проблема будет решена

Вот ответ в прекрасном и счастливом мире JetPack Compose:

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

Положил maxLines а также scrollbars внутри TextView в XML.

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

Тогда в коде Java.

textView.setMovementMethod(new ScrollingMovementMethod());

Используйте это так

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

В моем случае. Ограничение Layout.AS 2.3.

Реализация кода:

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML:

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

Для вертикально или горизонтально прокручиваемого TextView помогают некоторые другие ответы, но мне нужно было прокручивать в обоих направлениях.

Наконец, сработало ScrollView с HorizontalScrollView внутри и TextView внутри HSV. Он очень гладкий и может легко перемещаться из стороны в сторону или сверху вниз одним движением. Он также позволяет прокручивать только в одном направлении за раз, поэтому нет никакого прыжка из стороны в сторону при прокрутке вверх или вниз.

EditText с отключенным редактированием и курсором работает, но ужасно. Каждая попытка прокрутки перемещает курсор, и для перемещения сверху вниз или из стороны в сторону требуется много движений даже в файле размером ~100 строк.

С помощью setHorizontallyScrolling(true) может работать, но нет аналогичного метода, позволяющего вертикальную прокрутку, и он не работает внутри ScrollView, насколько я могу судить (хотя просто учусь, может быть неправильно).

Я боролся с этим больше недели и наконец понял, как заставить это работать!

Моя проблема заключалась в том, что все будет прокручиваться как "блок". Сам текст прокручивался, но не как строка за строкой, а как кусок. Это, очевидно, не работает для меня, потому что это будет отрезать линии внизу. Все предыдущие решения не работали для меня, поэтому я разработал собственное.

Вот самое простое решение на сегодняшний день:

Создайте файл класса с именем: '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;
    }
}

Наконец, измените ваш TextView в XML:

От: <TextView

Для того, чтобы: <com.your_app_goes_here.PerfectScrollableTextView

Другие вопросы по тегам