Делаем 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);
    }
}
EddieB
источник
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());
matasoy
источник
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();.
Samuh
источник
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);
IT-Dan
источник
Включает синюю анимацию. Лучший ответ здесь ИМО.
Гриффин В.
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.

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

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

android.weasel
источник
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());
Ritesh
источник
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"
Саша 888
источник
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

Petro
источник
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());

Khemraj
источник
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)

гашиш
источник
0

Попробуй это:

android:scrollbars = "vertical"
Мохамад Шейхи
источник