Здійснення прокрутки TextView на Android


771

Я відображаю текст у текстовому перегляді, який здається занадто довгим, щоб поміститися на одному екрані. Мені потрібно зробити свій 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);

Відповіді:


1719

Вам не потрібно використовувати 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
Щоб уточнити, що всі говорять про "плавне" прокручування: Якщо ви використовуєте цей метод, прокрутка насправді є "гладкою" (завдяки чому можна прокручувати піксель за пікселем), однак це не кінетично. Як тільки ви виймаєте палець, він миттєво перестає прокручуватися - ніякого миготіння немає. Це досить неприйнятно для сучасного інтерфейсу, тому я збираюсь відредагувати відповідь, щоб переконатися, що інші люди не витрачають час на це "рішення".
Timmmm

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

  2. Визначаючи перегляд прокрутки, НЕ вказуйте android:layout_height="fill_parent"інакше прокрутка не працює! (це зараз змусило мене витрачати годину! FFS).

ПОРАДА ПРО:

Щоб програматично прокрутити донизу після додавання тексту, використовуйте це:

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або інше ScrollViewможе бути марним (я видалив LinearLayoutповністю). Він також попереджає, що для TextViewцього слід android:layout_height="wrap_content"відповідати ScrollView. Ці попередження можуть бути наслідком 3 років, що минули з моменту опублікування цієї відповіді. Незважаючи на це, ця відповідь підтримує плавне прокручування та клацання ... + 1
skia.heliou

Додавання <!--suppress AndroidLintUselessParent -->вище ScrollViewу файл xml допоможе цим попередженням.
Луї Бертонцин

"Про рада" не працює для мене в Android API рівня 9. Перегляд тексту залишається прокрученим до верху після додавання тексту.
LarsH

Цей підхід набагато краще, якщо прийнятий підхід відповіді не створюватиме спокійного досвіду користувача.
seyedrezafar

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, я збираюся змінити текст на ньому, але його положення залишається прокрученим, навіть якщо це не потрібно. попередньо я застосував прокрутку ...
Nirav Dangi

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

1
Використовуйте StringBuilderзамість String... те, що у вас є, трохи марно.
Алекс Локвуд

4
це працює, але прокрутка не є рівною. Все ще працює, хоча дякую.
frostymarvelous

46

Зробіть текст перегляду, просто додавши це

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

16
Це не робить кінетичної прокрутки. Не використовуйте це.
Timmmm

3
@Timmmm як отримати кінетичну прокрутку?
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

Ви не хочете "кінетичної прокрутки" для тексту, який потрібно прочитати.
Неймовірний січень

41

Не потрібно ставити

android:Maxlines="AN_INTEGER"`

Ви можете зробити свою роботу, просто додавши:

android:scrollbars = "vertical"

І введіть цей код у свій клас Java:

textview.setMovementMethod(new ScrollingMovementMethod());

Набагато краще рішення, ніж прийняте, оскільки розмір смуги прокрутки точно відповідає тексту, і ви не витрачаєте місця.
FractalBob

коли я використовую ScrollView як батьків, цей час його не працює
Принц

27

Ви можете будь-який

  1. оточити TextViewa 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 IS TextView з декількома доданими методами та перестановками, спеціально розробленими для розміщення тексту різної довжини. Зокрема EditText перевизначає повернене значення для функції TextView getDefaultMovementMethod TextView. Реалізація за замовчуванням повертає 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 TextView. Він буде прокручуватися автоматично вниз, коли надходить більше тексту.

Звичайно, вам потрібно додати текст за допомогою функції додавання замість заданого тексту:

    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 () зробить це так, що ви не будете прокручуватиToBottom (), якщо користувач знаходиться в одному рядку від кінця ScrollView.


10

Якщо ви хочете, щоб текст прокручувався в текстовому перегляді, ви можете виконати наступне:

Спочатку вам доведеться переглядати текст підкласу.

А потім скористайтеся цим.

Далі наводиться приклад підкласового перегляду тексту.

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
Це не робить кінетичної прокрутки. Не використовуйте.
Timmmm

6

Я не знайшов прокрутку TextView, щоб підтримати жест 'fling', де він продовжує прокручуватись після натискання вгору чи вниз. Я в кінцевому підсумку реалізував це, тому що я не хотів використовувати ScrollView з різних причин, і не здавалося, що MovementMethod дозволив мені вибрати текст і натискати на посилання.


6
soo ... як ти додав жест флінгу?
Лу Морда

6

У kotlin для того, щоб зробити перегляд тексту прокручуваним

myTextView.movementMethod= ScrollingMovementMethod()

а також додайте в xml цю властивість

    android:scrollbars = "vertical"

5

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

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

чувак, tablecroller - це погляд, який був ідентифікований за атрибутом id з XML, який був оброблений в .. u просто спробуй .. він буде добре працювати .. його роботи від мене ..
Рахул Барадія

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
Це не робить кінетичної прокрутки. Не використовуйте.
Timmmm

я не хочу еліпсизувати кінцевий текст. як я це роблю
Сагар Наяк

@SagarNayak використовуйте android: ellipsize = "none"
Francis Francis

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

У моєму випадку. Макет обмеження.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 як метод батьків або прокрутки, тоді ви також використовуєте нижче описання.

Якщо у вас немає проблем, ви використовуєте 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 атрибут

Чи допускається, щоб текст був ширшим за перегляд (і тому його можна прокручувати по горизонталі).

Може бути булевим значенням, таким як "true" або "false".

Prigramacaly - setHorizontallyScrolling(boolean)


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.