Tornando o TextView rolável no Android


772

Estou exibindo texto em uma visualização de texto que parece ser muito longa para caber em uma tela. Preciso tornar meu TextView rolável. Como eu posso fazer isso?

Aqui está o 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);

Respostas:


1722

Você não precisa usar um ScrollViewrealmente.

Basta definir o

android:scrollbars = "vertical"

propriedades do seu TextViewarquivo xml do seu layout.

Então use:

yourTextView.setMovementMethod(new ScrollingMovementMethod());

no seu código.

Bingo, rola!


96
Mas certamente maxLinesexige que você digite um número arbitrário; isso não é algo que funcione para todos os tamanhos de tela e fontes? Acho mais simples envolvê-lo com a ScrollView, o que significa que não preciso adicionar mais nenhum atributo ou código XML (como definir o método de movimento).
Christopher Orr

12
@ Christopher, ScrollView requer 'android: layout_height' também.
Regex Rookie

11
@ Regex: Bem, sim. Você deixa ScrollViewocupar o espaço necessário (por exemplo, através do android:fillViewportatributo) ou define o tamanho específico que deseja. O uso maxLinesnão deve ser usado para definir tamanhos de elementos da interface do usuário, para que não haja solução.
Christopher Orr

62
você não precisa definir linhas máximas. apenas o resto.
Stevanicus

13
Para esclarecer o que todo mundo está dizendo sobre rolagem "suave": Se você usar esse método, a rolagem é realmente "suave" (na medida em que você pode rolar pixel por pixel), no entanto, não é cinético. Assim que você remove o dedo, ele para de rolar instantaneamente - não há movimento. Isso é bastante inaceitável para uma interface de usuário moderna, então vou editar a resposta para garantir que outras pessoas não percam tempo com essa "solução".
Timmmm

310

Foi assim que fiz puramente em 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 com android:layout_weight="1.0"fará com que a visualização de texto ocupe todo o espaço disponível.

  2. Ao definir o Scrollview, NÃO especifique, android:layout_height="fill_parent"caso contrário, o scrollview não funcionará! (isso me levou a perder uma hora agora! FFS).

DICA PRO:

Para rolar programaticamente até o final após anexar o texto, use o seguinte:

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
Não há necessidade de usar mTextView.getBottom(), basta usar o método mScrollView.fullScroll(View.FOCUS_DOWN), pois faz parte da API ScrollView. Veja aqui e aqui para mais informações.
ChuongPham

7
O Android avisa que o LinearLayoutou o ScrollViewpode ser inútil neste exemplo (eu removi o LinearLayoutcompletamente). Ele também adverte que, para o TextView, deve ser android:layout_height="wrap_content"igual ao ScrollView. Esses avisos podem ocorrer devido aos três anos que se passaram desde que esta resposta foi publicada. Independentemente disso, esta resposta suporta rolagem suave e movimento
rápido

A adição <!--suppress AndroidLintUselessParent -->acima do ScrollViewarquivo xml cuidará desses avisos.
Louie Bertoncin

A "dica profissional" não funciona para mim, no nível 9. da API do Android. A visualização de texto permanece rolada para o topo depois de anexar o texto.
LarsH 21/04

Essa abordagem é muito melhor, usando a abordagem de resposta aceita não produzirá uma experiência suave para o usuário.
seyedrezafar

120

Tudo o que é realmente necessário é o setMovementMethod (). Aqui está um exemplo usando um LinearLayout.

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

Arquivo 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
Existe alguma maneira de definir essa propriedade em XML? Eu me pergunto por que eles deixariam de fora essa opção.
Thalur

Funciona, mas existe alguma maneira de atualizá-lo após a rolagem? quero dizer, depois de rolar o TextView, vou mudar o texto, mas sua posição permanece rolada, mesmo que não seja necessária. sua bcose anteriormente eu tinha aplicado rolagem ...
Nirav Dangi

9
sem barras de rolagem e a rolagem é desajeitada em comparação com o ScrollViewmétodo
Jeffrey Blattman

1
Use um em StringBuildervez de um String... o que você tem é um pouco de desperdício.
Alex Lockwood

4
isso funciona, mas a rolagem não é suave. Ainda funciona embora obrigado.
Frostymarvelous 15/07

46

Crie sua visualização de texto apenas adicionando isso

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

16
Isso não faz rolagem cinética. Não use isso.
Timmmm

3
@Timmmm como obter o rolo cinético?
Ciro Santilli #

Você não deseja "rolagem cinética" para um texto que precisa ser lido.
O incrível Jan

41

Não é necessário colocar

android:Maxlines="AN_INTEGER"`

Você pode fazer seu trabalho simplesmente adicionando:

android:scrollbars = "vertical"

E, coloque este código na sua classe Java:

textview.setMovementMethod(new ScrollingMovementMethod());

Solução muito melhor que a aceita, pois o tamanho da barra de rolagem se encaixa exatamente no texto e você não perde espaço.
FractalBob

quando eu estou usando ScrollView como pai, que o tempo não o seu trabalho
Príncipe

27

Você também pode

  1. rodeie o TextViewpor um ScrollView; ou
  2. defina o método Movement para ScrollingMovementMethod.getInstance();.

22

A melhor maneira que encontrei:

Substitua o TextView por um EditText por estes atributos extras:

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

Não há necessidade de agrupar em um ScrollView.


2
Facilmente a resposta melhor e mais apropriada, especialmente considerando que o EditText é uma subclasse TextView e a questão é como tornar a visualização de texto rolável, não como solucionar o problema. Votariam duas vezes se eu pudesse :)
Justin Buser

4
@JustinBuser Não poderia discordar mais. :) É puramente acidental que isso funcione, e não há garantia de que funcione nas versões futuras do Android. Se você quiser rolar, use as ferramentas de rolagem fornecidas pelo Android. ScrollViewé o caminho correto a seguir.
Madbreaks

1
@ Madbreaks Não há nada de "acidental", o EditText IS é um TextView com alguns métodos e substituições adicionados, especificamente adaptados para acomodar textos de tamanhos variados. Em particular, o EditText substitui o valor de retorno da função TextView getDefaultMovementMethod. A implementação padrão retorna NULL, EditText basicamente faz a mesma coisa que todas essas outras respostas estão sugerindo. No que diz respeito ao uso das ferramentas fornecidas pelo Android, é muito menos provável que a classe EditText fique obsoleta do que qualquer outro método encontrado nessas respostas.
Justin Buser

4
@JustinBuser Meu problema com isso, porém, é que você depende do comportamento padrão do EditText, e foi isso que eu quis dizer pode muito bem mudar no futuro (nem um pouco que o EditText seria descontinuado). Você pode argumentar que, porém, novamente, a idéia é usar componentes e recursos apropriados para a tarefa em questão. O ScrollView foi projetado explicitamente para abranger a rolagem. Eu sempre tento, e sempre sugiro que outras pessoas usem a ferramenta certa para o trabalho. Quase sempre existem várias abordagens para qualquer problema de programação. De qualquer forma, obrigado pela resposta atenciosa.
Madbreaks

16

Simples. Foi assim que eu fiz:

  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 do Java:

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

Bônus:

Para permitir que a exibição de texto role para baixo conforme o texto a preenche, é necessário adicionar:

    android:gravity="bottom"

para o arquivo xml TextView. Ele irá rolar para baixo automaticamente à medida que mais texto aparecer.

Obviamente, você precisa adicionar o texto usando a função anexar em vez do texto definido:

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

Eu usei para fins de log.

Eu espero que isso ajude ;)


14

Isso é "Como aplicar o ScrollBar ao seu TextView", usando apenas XML.

Primeiro, você precisa pegar um controle Textview no arquivo main.xml e escrever algum texto nele ... assim:

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

Em seguida, coloque o controle de exibição de texto entre a visualização de rolagem para exibir a barra de rolagem 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>

É isso aí...


6
Por que escrever isso? Essa é uma versão quase idêntica, embora menos correta, de uma resposta publicada mais de 6 meses antes de você a escrever.
Justin Buser

11

Isso fornecerá texto de rolagem suave com uma barra de rolagem.

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

Ativa animação azul. Melhor resposta aqui IMO.
Griffin W.

11

A "dica profissional" acima de Someone Somewhere ( tornando o TextView rolável no Android ) funciona muito bem, no entanto, e se você estiver adicionando texto dinamicamente ao ScrollView e quiser rolar automaticamente para baixo depois de apenas um acréscimo quando o usuário estiver em a parte inferior do ScrollView? (Talvez porque se o usuário rolou para cima para ler algo que você não deseja redefinir automaticamente para baixo durante um anexo, o que seria irritante.)

Enfim, aqui está:

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

O mTextStatus.getLineHeight () fará com que você não roleToBottom () se o usuário estiver dentro de uma linha a partir do final do ScrollView.


10

Se você deseja que o texto seja rolado na visualização de texto, siga o seguinte:

Primeiro, você deve subclassar a visualização de texto.

E então use isso.

A seguir, é apresentado um exemplo de uma exibição de texto em subclasse.

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

Agora, você deve usar isso no XML desta maneira:

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

É isso aí.


7

Adicione o seguinte na visualização de texto em XML.

android:scrollbars="vertical"

E finalmente, adicione

textView.setMovementMethod(new ScrollingMovementMethod());

no arquivo Java.


1
Isso não faz rolagem cinética. Não use isso.
Timmmm

6

Não encontrei a rolagem do TextView para suportar o gesto de 'arremessar', onde continua rolando após um movimento para cima ou para baixo. Acabei implementando isso sozinho porque não queria usar o ScrollView por vários motivos, e não parecia haver um MovementMethod que permitisse selecionar texto e clicar em links.


6
soo ... como você adicionou o gesto de arremesso?
9788 Louise Morda

6

No kotlin para tornar a visualização de texto rolável

myTextView.movementMethod= ScrollingMovementMethod()

e também adicione em xml essa propriedade

    android:scrollbars = "vertical"

5

Ao concluir a rolagem, adicione esta linha à última linha da exibição ao inserir qualquer coisa na exibição:

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

cara, tablescroller é uma visão que foi identificado pelo atributo id do XML que foi processado em .. u apenas experimentá-lo .. ele vai funcionar bem .. suas obras fr mim ..
Rahul Baradia

4

Se você não quiser usar a solução EditText, poderá ter melhor sorte com:

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

4

Adicione isso ao seu 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 no código você deve escrever as seguintes linhas:

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

2
Isso não faz rolagem cinética. Não use isso.
Timmmm

Eu não quero elipsize o texto final. Como eu faço isso.
Sagar Nayak

@SagarNayak usar o Android: ellipsize = "none"
Francis

2

O código abaixo cria uma visualização de texto de rolagem horizontal automática:

Ao adicionar o TextView ao xml, use

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

Defina as seguintes propriedades do TextView em onCreate ()

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


1

Use-o assim

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

0

No meu caso.Constraint Layout.AS 2.3.

Implementação de código:

YOUR_TEXTVIEW.setMovementMethod(new ScrollingMovementMethod());

XML:

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

0

Eu lutei com isso por mais de uma semana e finalmente descobri como fazer isso funcionar!

Meu problema era que tudo rolaria como um 'bloco'. O texto em si estava rolando, mas como um pedaço, em vez de linha por linha. Obviamente, isso não funcionou para mim, porque cortaria as linhas na parte inferior. Todas as soluções anteriores não funcionaram para mim, então criei as minhas.

Aqui está a solução mais fácil de longe:

Crie um arquivo de classe chamado: 'PerfectScrollableTextView' dentro de um pacote e copie e cole esse código em:

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

Por fim, altere seu 'TextView' em XML:

De: <TextView

Para: <com.your_app_goes_here.PerfectScrollableTextView


1
Resposta 100% perfeita. Eu enfrentei o mesmo problema que você mencionou na descrição. aplique muitas soluções, mas não funcione perfeitamente. mas sua solução está funcionando perfeitamente em todos os casos. save my time man :) Obrigado
Daxesh Vekariya 02/01

@DaxeshVekariya Fico feliz que funcionou para você!
Petro

0

Coloque maxLinese scrollbarsdentro do TextView em xml.

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

Então no código java.

textView.setMovementMethod(new ScrollingMovementMethod());


0

Eu tive esse problema quando estava usando TextViewdentro do ScrollView. Esta solução funcionou para mim.

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

sempre que você precisar usar o ScrollView como pai e também usar o método de movimento de rolagem com o TextView.

E quando você retrata a paisagem do seu dispositivo nesse momento, ocorre algum problema . (como) a página inteira é rolável, mas o método de movimento de rolagem não pode funcionar.

se você ainda precisar usar o ScrollView como pai ou método de movimento de rolagem, use também abaixo de desc.

Se você não tiver nenhum problema, use EditText em vez de TextView

ver abaixo :

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

Aqui, o EditText se comporta como TextView

E seu problema será resolvido


0

XML - você pode usar o android:scrollHorizontallyatributo

Se é permitido que o texto seja maior que a visualização (e, portanto, pode ser rolado horizontalmente).

Pode ser um valor booleano, como "true" ou "false".

Prigramacaly - setHorizontallyScrolling(boolean)


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.