Hacer que TextView se pueda desplazar en Android

772

Estoy mostrando texto en una vista de texto que parece ser demasiado larga para caber en una pantalla. Necesito hacer mi TextView desplazable. ¿Cómo puedo hacer eso?

Aquí está el código:

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);
Muhammad Maqsoodur Rehman
fuente

Respuestas:

1722

No necesita usar un en ScrollViewrealidad.

Solo configura el

android:scrollbars = "vertical"

propiedades de su TextViewen el archivo xml de su diseño.

Luego use:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

en tu código

Bingo, se desplaza!

Amit Chintawar
fuente
96
Pero seguramente maxLinesrequiere que ingrese un número arbitrario; ¿Esto no es algo que funcione para cada tamaño de pantalla y tamaño de fuente? Me parece más simple simplemente envolverlo con un ScrollView, lo que significa que no tengo que agregar ningún atributo o código XML adicional (como configurar el método de movimiento).
Christopher Orr
12
@Christopher, ScrollView requiere 'android: layout_height' también.
Regex Rookie
11
@Regex: Bueno, sí. O deja que ScrollViewocupe todo el espacio que necesita (por ejemplo, a través del android:fillViewportatributo), o establece el tamaño específico que desea. El uso maxLinesno debe usarse para establecer tamaños de elementos de la interfaz de usuario, por lo que no es una solución.
Christopher Orr
62
no necesita definir maxlines. solo el resto
Stevanicus
13
Para aclarar lo que todo el mundo está diciendo acerca de "suavizar" el desplazamiento: Si se utiliza este método de desplazamiento es en realidad "suave" (en la que puede desplazarse píxel por píxel), sin embargo, es que no cinética. Tan pronto como retire su dedo, deja de desplazarse instantáneamente, no hay movimiento. Esto es bastante inaceptable para una IU moderna, así que voy a editar la respuesta para asegurarme de que otras personas no pierdan el tiempo con esta "solución".
Timmmm
310

Así es como lo hice puramente en 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>

NOTAS

  1. android:fillViewport="true"combinado con android:layout_weight="1.0"hará que la vista de texto ocupe todo el espacio disponible.

  2. Al definir la vista de desplazamiento, ¡NO especifique lo android:layout_height="fill_parent"contrario, la vista de desplazamiento no funciona! (¡Esto me ha hecho perder una hora ahora mismo! FFS).

CONSEJO PRO:

Para desplazarse programáticamente a la parte inferior después de agregar texto, use esto:

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());
        }
    });
}
Alguien en alguna parte
fuente
12
No es necesario usarlo mTextView.getBottom(), solo use el método mScrollView.fullScroll(View.FOCUS_DOWN)ya que es parte de la API ScrollView. Vea aquí y aquí para más información.
ChuongPham
77
Android advierte que el LinearLayouto el ScrollViewpueden ser inútiles en este ejemplo (eliminé el LinearLayoutcompletamente). También advierte que para el TextView, debe ser android:layout_height="wrap_content"coincidir con el ScrollView. Estas advertencias pueden deberse a los 3 años que han pasado desde que se publicó esta respuesta. En cualquier caso, esta respuesta admite un desplazamiento y un desplazamiento suaves ... + 1
skia.heliou
Agregar <!--suppress AndroidLintUselessParent -->encima del ScrollViewarchivo xml se encargará de esas advertencias.
Louie Bertoncin
El "consejo profesional" no funciona para mí, en el nivel 9 de la API de Android. La vista de texto se desplaza a la parte superior después de agregar texto.
LarsH
Este enfoque es mucho mejor usando el enfoque de respuesta aceptado no producirá una experiencia de usuario fluida.
seyedrezafar
120

Todo lo que es realmente necesario es setMovementMethod (). Aquí hay un ejemplo usando un LinearLayout.

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

Archivo 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
fuente
3
¿Hay alguna forma de establecer esta propiedad en XML? Me pregunto por qué dejarían de lado esa opción.
Thalur
Funciona, pero ¿hay alguna forma de actualizarlo después de desplazarse? Es decir, después de desplazar TextView, voy a cambiar el texto, pero su posición permanece desplazada incluso si no es necesario. su bcose previamente había aplicado desplazamiento ...
Nirav Dangi
99
no hay barras de desplazamiento, y el desplazamiento es torpe en comparación con el ScrollViewmétodo.
Jeffrey Blattman
1
Use un en StringBuilderlugar de un String... lo que tiene es un poco derrochador.
Alex Lockwood
44
esto funciona pero el desplazamiento no es suave. Aún funciona, aunque gracias.
frostymarvelous
46

Haga su vista de texto simplemente agregando esto

TextView textview= (TextView) findViewById(R.id.your_textview_id);
textview.setMovementMethod(new ScrollingMovementMethod());
matasoy
fuente
16
Esto no hace desplazamiento cinético. No uses esto.
Timmmm
3
@Timmmm ¿cómo obtener el pergamino cinético?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
No desea "desplazamiento cinético" para un texto que debe leerse.
El increíble Jan
41

No es necesario poner

android:Maxlines="AN_INTEGER"`

Puedes hacer tu trabajo simplemente agregando:

android:scrollbars = "vertical"

Y, ponga este código en su clase Java:

textview.setMovementMethod(new ScrollingMovementMethod());
Ahsan Raza
fuente
Una solución mucho mejor que la aceptada, ya que el tamaño de la barra de desplazamiento se ajusta exactamente al texto y no desperdicia espacio.
FractalBob
cuando estoy usando ScrollView como padre, esa vez no funciona
Prince
27

Tu también puedes

  1. rodear el TextViewpor a ScrollView; o
  2. establece el método de movimiento en ScrollingMovementMethod.getInstance();.
Samuh
fuente
22

La mejor manera que encontré:

Reemplace TextView con un EditText con estos atributos adicionales:

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

No hay necesidad de envolver en un ScrollView.

Valentin Galea
fuente
2
Fácilmente la respuesta mejor y más apropiada, especialmente teniendo en cuenta que EditText es una subclase TextView y la pregunta es cómo hacer que la vista de texto se pueda desplazar, no cómo solucionar el problema. Votaría dos veces si pudiera :)
Justin Buser
44
@JustinBuser No podría estar más en desacuerdo. :) Es pura casualidad que esto funcione, y no hay garantía de que lo haga en futuras versiones de Android. Si desea desplazarse, use las herramientas de desplazamiento que proporciona Android. ScrollViewEs el camino correcto a seguir.
Madbreaks
1
@Madbreaks No hay nada "fortuito" al respecto, EditText ES un TextView con algunos métodos agregados y anulaciones que está específicamente diseñado para acomodar texto de longitud variable. En particular, EditText anula el valor de retorno de la función TextView getDefaultMovementMethod. La implementación predeterminada devuelve NULL, EditText básicamente hace lo mismo que sugieren todas estas otras respuestas. En lo que respecta al uso de las herramientas que ofrece Android, es mucho menos probable que la clase EditText quede obsoleta que cualquiera de los otros métodos encontrados en estas respuestas.
Justin Buser
44
@JustinBuser Mi problema con eso es que depende del comportamiento predeterminado de EditText, eso es lo que quise decir que podría cambiar en el futuro (en absoluto, EditText sería obsoleto). Puede argumentar que, pero de nuevo, la idea es usar componentes y características que sean apropiados para la tarea en cuestión. ScrollView fue diseñado explícitamente para abarcar el desplazamiento. Siempre trato de, y siempre sugiero que otros usen la herramienta adecuada para el trabajo. Casi siempre hay múltiples enfoques para cualquier problema de programación dado. De todos modos, gracias por la atenta respuesta.
Madbreaks
16

Simple. Así es como lo hice:

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

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

Prima:

Para permitir que la vista de texto se desplace hacia abajo a medida que el texto lo llena, debe agregar:

    android:gravity="bottom"

al archivo XML TextView. Se desplazará hacia abajo automáticamente a medida que ingrese más texto.

Por supuesto, debe agregar el texto utilizando la función de agregar en lugar de establecer el texto:

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

Lo usé para fines de registro.

Espero que esto ayude ;)

MBH
fuente
14

Esto es "Cómo aplicar ScrollBar a su TextView", utilizando solo XML.

Primero, debe tomar un control Textview en el archivo main.xml y escribir algo de texto en él ... de esta manera:

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

Luego, coloque el control de vista de texto entre la vista de desplazamiento para mostrar la barra de desplazamiento para este texto:

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

Eso es...

mOmO
fuente
66
¿Por qué incluso escribir esto? Esta es una versión casi idéntica, aunque menos correcta, de una respuesta que se publicó más de 6 meses antes de que la escribiera.
Justin Buser
11

Esto proporcionará un texto de desplazamiento suave con una barra de desplazamiento.

ScrollView scroller = new ScrollView(this);
TextView tv = new TextView(this);
tv.setText(R.string.my_text);
scroller.addView(tv);
IT-Dan
fuente
Habilita la animación azul. La mejor respuesta aquí OMI.
Griffin
11

Sin embargo, el "consejo profesional" anterior de Someone Somewhere ( Hacer que TextView se pueda desplazar en Android ) funciona de maravilla, ¿qué sucede si agrega texto dinámicamente a ScrollView y desea desplazarse automáticamente hacia la parte inferior después de un agregado solo cuando el usuario está en la parte inferior de ScrollView? (Quizás porque si el usuario se ha desplazado hacia arriba para leer algo que no desea restablecer automáticamente en la parte inferior durante un apéndice, lo que sería molesto).

De todos modos, aquí está:

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

El mTextStatus.getLineHeight () lo hará para que no se desplace a ToBottom () si el usuario está dentro de una línea desde el final de ScrollView.

Mark Cramer
fuente
10

Si desea que el texto se desplace dentro de la vista de texto, puede seguir lo siguiente:

Primero deberías subclasificar textview.

Y luego usa eso.

El siguiente es un ejemplo de una vista de texto subclasificada.

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

Ahora, tienes que usar eso en el XML de esta manera:

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

Eso es.

Dipendra
fuente
7

Agregue lo siguiente en la vista de texto en XML.

android:scrollbars="vertical"

Y finalmente, agregue

textView.setMovementMethod(new ScrollingMovementMethod());

en el archivo Java

usuario3921740
fuente
1
Esto no hace desplazamiento cinético. No lo uses.
Timmmm
6

No encontré el desplazamiento de TextView para admitir el gesto de 'lanzamiento', donde continúa desplazándose después de un movimiento hacia arriba o hacia abajo. Terminé implementando eso yo mismo porque no quería usar un ScrollView por varias razones, y no parecía haber un MoveMethod que me permitiera seleccionar texto y hacer clic en los enlaces.

android.weasel
fuente
66
entonces ... ¿cómo agregaste el gesto de lanzamiento?
Lou Morda
6

En kotlin por hacer que la vista de texto se pueda desplazar

myTextView.movementMethod= ScrollingMovementMethod()

y también agregue en xml esta propiedad

    android:scrollbars = "vertical"
Raluca Lucaci
fuente
5

Cuando haya terminado con el desplazamiento, agregue esta línea a la última línea de la vista cuando ingrese algo en la vista:

((ScrollView) findViewById(R.id.TableScroller)).fullScroll(View.FOCUS_DOWN);
Rahul Baradia
fuente
tio, tablescroller es una vista que fue identificado por el atributo id del XML que se procesa en .. u .. Haga la prueba que funciona bien .. ll sus obras me fr ..
Rahul Baradia
4

Si no desea utilizar la solución EditText, entonces podría tener mejor suerte con:

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

Agregue esto a su diseño 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"

Y en el código tienes que escribir las siguientes líneas:

textview.setSelected(true);
textView.setMovementMethod(new ScrollingMovementMethod());
Ritesh
fuente
2
Esto no hace desplazamiento cinético. No lo uses.
Timmmm
No quiero elipsar el texto final. cómo lo hago.
Sagar Nayak
@SagarNayak usa android: ellipsize = "none"
Francis
2

El siguiente código crea una vista de texto de desplazamiento horizontal automático:

Al agregar TextView al uso xml

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

Establezca las siguientes propiedades de TextView en onCreate ()

tv.setSelected(true);
tv.setHorizontallyScrolling(true); 
Perla blanca
fuente
1

Úselo así

<TextView  
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:maxLines = "AN_INTEGER"
    android:scrollbars = "vertical"
/>
Kamil Ibadov
fuente
0

En mi caso, diseño de restricción AS 2.3.

Implementación de código:

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML:

android:scrollbars="vertical"
android:scrollIndicators="right|end"
Sasha 888
fuente
0

¡Luché con esto durante más de una semana y finalmente descubrí cómo hacer que esto funcione!

Mi problema era que todo se desplazaría como un "bloque". El texto en sí se desplazaba, pero como un fragmento en lugar de línea por línea. Obviamente, esto no funcionó para mí, porque cortaría las líneas en la parte inferior. Todas las soluciones anteriores no me funcionaron, así que diseñé la mía.

Aquí está la solución más fácil con diferencia:

Cree un archivo de clase llamado: 'PerfectScrollableTextView' dentro de un paquete, luego copie y pegue este código en:

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 cambie su 'TextView' en XML:

Desde: <TextView

A: <com.your_app_goes_here.PerfectScrollableTextView

Petro
fuente
1
100% de respuesta perfecta. Me enfrenté al mismo problema que mencionas en la descripción. aplica muchas soluciones pero no funciona perfectamente. pero su solución funciona perfectamente en todos los casos. save my time man :) Gracias
Daxesh Vekariya
@DaxeshVekariya Me alegro de que te haya funcionado.
Petro
0

Poner maxLines y scrollbarsdentro de TextView en xml.

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

Luego en código java.

textView.setMovementMethod(new ScrollingMovementMethod());

Khemraj
fuente
0

Tuve este problema cuando estaba usando TextViewdentro de ScrollView. Esta solución me ha funcionado.

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;
            }
        });
Rohit Mandiwal
fuente
0

siempre que necesite usar ScrollView como padre , y también use el método de movimiento de desplazamiento con TextView.

Y cuando haces retratos para apaisar tu dispositivo, ese momento ocurre algún problema . (como) toda la página es desplazable pero el método de movimiento de desplazamiento no puede funcionar.

si todavía necesita usar ScrollView como método principal o de movimiento de desplazamiento, entonces también use la siguiente descripción.

Si no tiene ningún problema, use EditText en lugar de TextView

vea abajo :

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

Aquí, EditText se comporta como TextView

Y tu problema será resuelto

Príncipe
fuente
0

XML: puede usar android:scrollHorizontallyAttribute

Si se permite que el texto sea más ancho que la vista (y, por lo tanto, se puede desplazar horizontalmente).

Puede ser un valor booleano, como "verdadero" o "falso".

Prigramacaly - setHorizontallyScrolling(boolean)

picadillo
fuente
0

Prueba esto:

android:scrollbars = "vertical"
mohamad sheikhi
fuente