Rendere TextView scorrevole su Android


772

Sto visualizzando il testo in una visualizzazione di testo che sembra essere troppo lungo per adattarsi a una schermata. Devo rendere scorrevole il mio TextView. Come lo posso fare?

Ecco il codice:

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

Risposte:


1722

Non è necessario utilizzare un ScrollVieweffettivamente.

Basta impostare il

android:scrollbars = "vertical"

proprietà del tuo TextViewnel file xml del layout.

Quindi utilizzare:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

nel tuo codice.

Bingo, scorre!


96
Ma sicuramente maxLinesrichiede di inserire un numero arbitrario; questo non è qualcosa che funzionerà per ogni dimensione dello schermo e dimensione del carattere? Trovo più semplice racchiuderlo in a ScrollView, il che significa che non devo aggiungere ulteriori attributi o codice XML (come impostare il metodo di movimento).
Christopher Orr,

12
@Christopher, ScrollView richiede anche 'android: layout_height'.
Regex Rookie

11
@Regex: bene sì. O lasci che occupi lo ScrollViewspazio necessario (ad esempio tramite l' android:fillViewportattributo) o imposti la dimensione specifica che desideri. L'uso maxLinesnon deve essere usato per impostare dimensioni degli elementi dell'interfaccia utente, quindi non è una soluzione.
Christopher Orr,

62
non è necessario definire linee massime. solo il resto.
Stevanicus,

13
Per chiarire quello che tutti dicono di "liscio" scorrimento: Se si utilizza questo metodo di scorrimento è in realtà "liscio" (nel senso che è possibile scorrere pixel per pixel), ma è non è cinetica. Non appena si toglie il dito, lo scorrimento si interrompe istantaneamente, senza sfarfallio. Questo è inaccettabile per un'interfaccia utente moderna, quindi ho intenzione di modificare la risposta per assicurarmi che altre persone non perdano tempo in questa "soluzione".
Timmmm,

310

Questo è come l'ho fatto puramente in 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>

APPUNTI:

  1. android:fillViewport="true"combinato con android:layout_weight="1.0"renderà la visualizzazione del testo occupare tutto lo spazio disponibile.

  2. Quando si definisce la vista di scorrimento, NON specificare android:layout_height="fill_parent"altrimenti la vista di scorrimento non funziona! (questo mi ha fatto perdere un'ora proprio ora! FFS).

SUGGERIMENTO PRO:

Per scorrere programmaticamente verso il basso dopo aver aggiunto il testo, utilizzare questo:

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
Non è necessario utilizzare mTextView.getBottom(), basta usare il metodo mScrollView.fullScroll(View.FOCUS_DOWN)in quanto fa parte dell'API ScrollView. Vedi qui e qui per maggiori informazioni.
ChuongPham,

7
Android avverte che il LinearLayouto il ScrollViewpotrebbe essere inutile in questo esempio (ho rimosso LinearLayoutcompletamente). Inoltre avverte che per il TextView, dovrebbe essere android:layout_height="wrap_content"per abbinare il ScrollView. Questi avvisi potrebbero essere dovuti ai 3 anni trascorsi da quando è stata pubblicata questa risposta. Indipendentemente da ciò, questa risposta supporta lo scorrimento regolare e lo sfarfallio ... + 1
skia.heliou

L'aggiunta <!--suppress AndroidLintUselessParent -->sopra il ScrollViewfile nel file xml si occuperà di quegli avvisi.
Louie Bertoncin,

Il "suggerimento professionale" non funziona per me, nel livello API di Android 9. La visualizzazione del testo rimane in alto dopo aver aggiunto il testo.
LarsH,

Questo approccio è molto meglio utilizzando l'approccio con risposta accettata non produrrà un'esperienza utente fluida.
seyedrezafar,

120

Tutto ciò che è veramente necessario è setMovementMethod (). Ecco un esempio usando un LinearLayout.

File 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

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
C'è un modo per impostare questa proprietà in XML? Mi chiedo perché lascerebbero fuori quell'opzione.
Thalur,

Funziona ma è possibile aggiornarlo dopo lo scorrimento? intendo dopo aver fatto scorrere il TextView ho intenzione di cambiare il testo su di esso, ma la sua posizione rimane scorrevole anche se non è richiesta. è perché in precedenza avevo applicato scroll ...
Nirav Dangi il

9
nessuna barra di scorrimento e lo scorrimento è grosso rispetto al ScrollViewmetodo.
Jeffrey Blattman,

1
Usa un StringBuilderinvece di un String... quello che hai è un po 'dispendioso.
Alex Lockwood,

4
funziona ma lo scorrimento non è regolare. Funziona comunque grazie.
frostymarvelous,


41

Non è necessario inserire

android:Maxlines="AN_INTEGER"`

Puoi fare il tuo lavoro semplicemente aggiungendo:

android:scrollbars = "vertical"

E, inserisci questo codice nella tua classe Java:

textview.setMovementMethod(new ScrollingMovementMethod());

Soluzione molto migliore di quella accettata, poiché le dimensioni della barra di scorrimento si adattano esattamente al testo e non perdi spazio.
FractalBob

quando sto usando ScrollView come genitore, quella volta non funziona
Prince

27

Puoi farlo

  1. circondare la TextViewa ScrollView; o
  2. impostare il metodo di movimento su ScrollingMovementMethod.getInstance();.

22

Il modo migliore che ho trovato:

Sostituisci TextView con un EditText con questi attributi extra:

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

Non è necessario eseguire il wrapping in ScrollView.


2
Facilmente la risposta migliore e più appropriata, soprattutto considerando che EditText è una sottoclasse di TextView e la domanda è come rendere scorrevole la visualizzazione del testo, non come aggirare il problema. Vorrei votare due volte se potessi :)
Justin Buser

4
@JustinBuser Non potrei essere più in disaccordo. :) È puramente casuale che funzioni e non c'è garanzia che lo farà nelle future versioni di Android. Se si desidera scorrere, utilizzare gli strumenti di scorrimento forniti da Android. ScrollViewè la strada giusta da percorrere.
Madbreaks,

1
@Madbreaks Non c'è nulla di "serendipitous" al riguardo, EditText È un TextView con alcuni metodi aggiunti e sostituzioni che è specificamente su misura per adattarsi a testi di lunghezza variabile. In particolare EditText sovrascrive il valore restituito per la funzione getViewDefaultMovementMethod di TextView. L'implementazione predefinita restituisce NULL, in sostanza EditText fa la stessa cosa che tutte queste altre risposte suggeriscono. Per quanto riguarda l'utilizzo degli strumenti forniti da Android, la classe EditText ha molte meno probabilità di diventare obsoleta rispetto a qualsiasi altro metodo trovato in queste risposte.
Justin Buser,

4
@JustinBuser Il mio problema è che dipende dal comportamento predefinito di EditText, questo è ciò che intendevo potrebbe benissimo cambiare lungo la strada (per niente EditText sarebbe deprecato). Si può sostenere che, ma ancora una volta, l'idea è quella di utilizzare componenti e funzionalità appropriati per l'attività in corso. ScrollView è stato progettato esplicitamente per comprendere lo scorrimento. Cerco sempre di suggerire e suggerisco sempre ad altri di usare lo strumento giusto per il lavoro. Esistono quasi sempre molteplici approcci a qualsiasi dato problema di programmazione. Comunque, grazie per la risposta premurosa.
Madbreaks,

16

Semplice. Ecco come l'ho fatto:

  1. Lato 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. Lato Java:

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

Bonus:

Per consentire alla visualizzazione del testo di scorrere verso il basso mentre il testo lo riempie, è necessario aggiungere:

    android:gravity="bottom"

nel file XML di TextView. Scorrerà automaticamente verso il basso man mano che entra più testo.

Ovviamente devi aggiungere il testo usando la funzione append invece di impostare il testo:

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

L'ho usato a scopo di registro.

Spero che questo possa essere d'aiuto ;)


14

Questo è "Come applicare ScrollBar al tuo TextView", usando solo XML.

Innanzitutto, devi prendere un controllo Textview nel file main.xml e scrivere del testo in esso ... in questo modo:

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

Quindi, posizionare il controllo di visualizzazione del testo tra la vista di scorrimento per visualizzare la barra di scorrimento per questo testo:

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

Questo è tutto...


6
Perché anche scrivere questo? Questa è una versione quasi identica, sebbene meno corretta, di una risposta che è stata pubblicata oltre 6 mesi prima che tu la scrivessi.
Justin Buser,

11

Ciò fornirà un testo scorrevole con una barra di scorrimento.

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

Abilita l'animazione blu. La migliore risposta qui IMO.
Griffin W.

11

Il "suggerimento pro" sopra di Someone Somewhere ( Rendere scorrevole TextView su Android ) funziona alla grande, tuttavia, cosa succede se stai aggiungendo dinamicamente testo a ScrollView e vorresti scorrere automaticamente verso il basso dopo un'appendice solo quando l'utente è a la parte inferiore di ScrollView? (Forse perché se l'utente ha fatto scorrere verso l'alto per leggere qualcosa che non si desidera ripristinare automaticamente in fondo durante un'appendice, il che sarebbe fastidioso.)

Ad ogni modo, eccolo qui:

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

MTextStatus.getLineHeight () lo farà in modo da non scorrereToBottom () se l'utente si trova all'interno di una riga dalla fine di ScrollView.


10

Se si desidera scorrere il testo all'interno della visualizzazione di testo, è possibile seguire quanto segue:

Per prima cosa dovresti sottoclassare la visualizzazione di testo.

E poi usalo.

Di seguito è riportato un esempio di una visualizzazione di testo sottoclassata.

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

Ora, devi usarlo nell'XML in questo modo:

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

Questo è tutto.


7

Aggiungi quanto segue nella visualizzazione di testo in XML.

android:scrollbars="vertical"

E infine, aggiungi

textView.setMovementMethod(new ScrollingMovementMethod());

nel file Java.


1
Questo non esegue lo scorrimento cinetico. Non usarlo.
Timmmm,

6

Non ho trovato lo scorrimento di TextView per supportare il gesto di "lancio", dove continua a scorrere dopo un movimento verso l'alto o verso il basso. Ho finito per implementarlo da solo perché non volevo usare uno ScrollView per vari motivi e non sembrava esserci un Metodo di movimento che mi permettesse di selezionare il testo e fare clic sui collegamenti.


6
soo ... come hai aggiunto il gesto dell'avventura?
Lou Morda,

6

In kotlin per rendere scorrevole la visualizzazione del testo

myTextView.movementMethod= ScrollingMovementMethod()

e aggiungi anche in xml questa proprietà

    android:scrollbars = "vertical"

5

Quando hai finito con lo scorrimento, aggiungi questa riga all'ultima riga della vista quando inserisci qualcosa nella vista:

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

amico, tablecroller è una vista che è stata identificata dall'attributo id dall'XML che è stato elaborato in .. lo provi e basta .. funzionerà bene .. funziona da me ..
Rahul Baradia

4

Se non desideri utilizzare la soluzione EditText, potresti avere più fortuna con:

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

4

Aggiungi questo al tuo 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"

E nel codice devi scrivere le seguenti righe:

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

2
Questo non esegue lo scorrimento cinetico. Non usarlo.
Timmmm,

non voglio ellissize il testo finale. come lo faccio.
Sagar Nayak,

@SagarNayak usa android: ellipsize = "none"
Francis

2

Il codice seguente crea una visualizzazione di testo a scorrimento orizzontale automatico:

Durante l'aggiunta di TextView a XML utilizzare

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

Impostare le seguenti proprietà di TextView in onCreate ()

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


1

Usalo in questo modo

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

0

Nel mio caso. Layout del vincolo. AS 2.3.

Implementazione del codice:

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML:

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

0

Ho lottato con questo per oltre una settimana e finalmente ho capito come farlo funzionare!

Il mio problema era che tutto scorreva come un "blocco". Il testo stesso stava scorrendo, ma come un pezzo piuttosto che riga per riga. Questo ovviamente non ha funzionato per me, perché avrebbe tagliato le linee in fondo. Tutte le soluzioni precedenti non funzionavano per me, quindi ho creato la mia.

Ecco di gran lunga la soluzione più semplice:

Crea un file di classe chiamato: "PerfectScrollableTextView" all'interno di un pacchetto, quindi copia e incolla questo codice in:

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

Finalmente cambia il tuo 'TextView' in XML:

A partire dal: <TextView

Per: <com.your_app_goes_here.PerfectScrollableTextView


1
Risposta perfetta al 100%. Ho riscontrato lo stesso problema menzionato nella descrizione. applica molte soluzioni ma non funziona perfettamente. ma la tua soluzione funziona perfettamente in ogni caso. risparmia tempo amico :) Grazie
Daxesh Vekariya il

@DaxeshVekariya Sono contento che abbia funzionato per te!
Petro

0

Inserisci maxLinese scrollbarsdentro TextView in xml.

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

Quindi nel codice Java.

textView.setMovementMethod(new ScrollingMovementMethod());


0

Ho avuto questo problema quando stavo usando TextViewall'interno di ScrollView. Questa soluzione ha funzionato per 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;
            }
        });

0

ogni volta che è necessario utilizzare ScrollView come genitore , e usi anche il metodo di movimento scroll con TextView.

E quando si esegue il ritratto in orizzontale del dispositivo in quel momento si verificano problemi . (come) l'intera pagina è scorrevole ma il metodo di spostamento dello scorrimento non può funzionare.

se è ancora necessario utilizzare ScrollView come metodo di spostamento principale o di scorrimento, utilizzare anche la seguente descrizione.

Se non si verificano problemi, utilizzare EditText anziché TextView

vedi sotto :

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

Qui, EditText si comporta come TextView

E il tuo problema verrà risolto


0

XML: è possibile utilizzare android:scrollHorizontally attributo

Se il testo può essere più largo della vista (e quindi può essere fatto scorrere in orizzontale).

Può essere un valore booleano, ad esempio "vero" o "falso".

Prigramacaly - setHorizontallyScrolling(boolean)


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.