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


772

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

Ответы:


1723

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

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

android:scrollbars = "vertical"

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

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

yourTextView.setMovementMethod(new ScrollingMovementMethod());

в вашем коде.

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


96
Но, безусловно, maxLinesтребует от вас ввести произвольное число; это не то, что будет работать для каждого размера экрана и размера шрифта? Я считаю, что проще просто обернуть его ScrollView, что означает, что мне не нужно добавлять какие-либо дополнительные атрибуты XML или код (например, установка метода движения).
Кристофер Орр

12
@Christopher, ScrollView также требует 'android: layout_height'.
Regex Rookie

11
@Regex: ну да. Либо вы позволяете ScrollViewоператору занимать столько места, сколько ему нужно (например, через android:fillViewportатрибут), либо вы устанавливаете нужный размер. Использование maxLinesне должно использоваться для установки размеров элементов пользовательского интерфейса, так что это не решение.
Кристофер Орр

62
Вам не нужно определять максимальные линии. просто остальное.
Стеваникус

13
Чтобы прояснить, что все говорят о «плавной» прокрутке: если вы используете этот метод, прокрутка на самом деле «плавная» (в том смысле, что вы можете прокручивать пиксель за пикселем), однако она не кинетическая. Как только вы убираете палец, он мгновенно прекращает прокрутку - щелчков нет. Это довольно неприемлемо для современного пользовательского интерфейса, поэтому я собираюсь отредактировать ответ, чтобы другие люди не тратили время на это «решение».
Тимммм

310

Вот как я сделал это чисто в 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"иначе scrollview не работает! (это заставило меня потратить впустую час только сейчас! 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());
        }
    });
}

12
Там нет необходимости использовать mTextView.getBottom(), просто используйте метод, mScrollView.fullScroll(View.FOCUS_DOWN)поскольку он является частью ScrollView API. Смотрите здесь и здесь для получения дополнительной информации.
ChuongPham,

7
Android предупреждает, что в этом примере может быть бесполезным или то, LinearLayoutили другое ScrollViewLinearLayoutполностью удалил ). Он также предупреждает, что для TextView, он должен android:layout_height="wrap_content"соответствовать ScrollView. Эти предупреждения могут быть связаны с 3 годами, прошедшими с момента публикации этого ответа. Несмотря на это, этот ответ поддерживает плавную прокрутку и щелчок ... + 1
skia.heliou

Добавление <!--suppress AndroidLintUselessParent -->выше ScrollViewв xml-файл позаботится об этих предупреждениях.
Луи Бертонсин

«Советы профессионалов» у меня не работают, на уровне API Android 9. Текстовое представление остается прокрученным до самого верха после добавления текста.
LarsH

Этот подход намного лучше, используя принятый подход ответа не будет производить гладкое взаимодействие с пользователем.
Сейедрезафар

120

Все, что действительно необходимо, это 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);
    }
}

3
Есть ли способ установить это свойство в XML? Интересно, почему они отказались от этого варианта?
Талур

Это работает, но есть ли способ обновить его после прокрутки? я имею в виду после прокрутки TextView я собираюсь изменить текст на нем, но его положение остается прокрученным, даже если это не требуется. его Bcos ранее я применил свиток ...
Нирав Dangi

9
полос прокрутки нет, и прокрутка неуклюжа по сравнению с ScrollViewметодом.
Джеффри Блатман

1
Используйте StringBuilderвместо String... то, что у вас есть, немного расточительно.
Алекс Локвуд

4
это работает, но прокрутка не гладкая. Все еще работает, хотя спасибо.
морозный

46

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

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

16
Это не делает кинетическую прокрутку. Не используйте это.
Тимммм

3
@Timmmm, как получить кинетический свиток?
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Вам не нужна «кинетическая прокрутка» для текста, который нужно прочитать.
Невероятный

41

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

android:Maxlines="AN_INTEGER"`

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

android:scrollbars = "vertical"

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

textview.setMovementMethod(new ScrollingMovementMethod());

Гораздо лучшее решение, чем принятое, поскольку размер полосы прокрутки точно соответствует тексту, и вы не теряете место.
FractalBob

когда я использую ScrollView в качестве родителя, это время не работает
Prince

27

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

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

22

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

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

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

Там нет необходимости для упаковки в ScrollView.


2
Легко самый лучший и наиболее подходящий ответ, особенно если учесть, что EditText является подклассом TextView, и вопрос заключается в том, как сделать прокручиваемый текстовый вид, а не как обойти проблему. Голосовал бы дважды, если бы мог :)
Джастин Бьюзер

4
@JustinBuser Не могу не согласиться. :) Это просто по счастливой случайности, что это работает, и нет никаких гарантий, что это будет в будущих версиях Android. Если вы хотите прокрутить, используйте инструменты прокрутки, которые предоставляет Android. ScrollViewэто правильный путь.
Madbreaks

1
@Madbreaks В этом нет ничего «случайного», EditText - это TextView с несколькими добавленными методами и переопределениями, специально предназначенными для размещения текста различной длины. В частности, EditText переопределяет возвращаемое значение для функции TextView getDefaultMovementMethod. Реализация по умолчанию возвращает NULL, EditText в основном делает то же самое, что предлагают все эти другие ответы. Что касается использования инструментов, предоставляемых Android, то класс EditText с меньшей вероятностью станет устаревшим, чем любой из других методов, найденных в этих ответах.
Джастин Бузер

4
@JustinBuser Моя проблема с этим, хотя вы в зависимости от поведения EditText по умолчанию, это то, что я имел в виду, вполне может измениться в будущем (совсем не то, что EditText будет устаревшим). Вы можете утверждать, что, но опять же, идея состоит в том, чтобы использовать компоненты и функции, которые соответствуют поставленной задаче. ScrollView был явно разработан, чтобы охватить прокрутку. Я всегда стараюсь и всегда предлагаю другим использовать правильный инструмент для работы. Почти всегда есть несколько подходов к любой заданной проблеме программирования. В любом случае, спасибо за вдумчивый ответ.
Madbreaks

16

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

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

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

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


14

Это «Как применить 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>

Это оно...


6
Зачем вообще это писать? Это почти идентичная, хотя и менее правильная версия ответа, которая была опубликована за 6 месяцев до того, как вы ее написали.
Джастин Бьюзер

11

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

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

Включает синюю анимацию. Лучший ответ здесь ИМО.
Гриффин В.

11

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

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

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

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


10

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

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

Вот и все.


7

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

android:scrollbars="vertical"

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

textView.setMovementMethod(new ScrollingMovementMethod());

в файле Java.


1
Это не делает кинетическую прокрутку. Не используйте его.
Тимммм

6

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


6
так ... как вы добавили жест броска?
Лу Морда

6

В kotlin для того, чтобы сделать прокручиваемый текстовый вид

myTextView.movementMethod= ScrollingMovementMethod()

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

    android:scrollbars = "vertical"

5

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

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

чувак, tablescroller - это представление, которое было идентифицировано атрибутом id из XML, который был обработан в ... ты просто попробуй это ... он будет работать нормально ... все работает со мной ..
Рахул Барадия

4

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

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

4

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

2
Это не делает кинетическую прокрутку. Не используйте его.
Тимммм

я не хочу увеличивать размер конечного текста. как это сделать.
Сагар Наяк

@SagarNayak использовать android: ellipsize = "нет"
Фрэнсис

2

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

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

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

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

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


1

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

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

0

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

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

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML:

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

0

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

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

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

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


1
100% идеальный ответ. Я столкнулся с той же проблемой, что вы упоминаете в описании. применять много решений, но не работают идеально. но ваше решение работает отлично в каждом случае. спаси мое время мужик :) Спасибо
Дакеш Векария

@DaxeshVekariya Рад, что это сработало для вас!
Петр

0

Положите 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());


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

0

всякий раз, когда вам нужно использовать 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

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


0

XML - вы можете использовать android:scrollHorizontallyатрибут

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

Может быть логическим значением, таким как «истина» или «ложь».

Приграмакалия - setHorizontallyScrolling(boolean)


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.