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

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!

Amit Chintawar
fonte
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());
        }
    });
}
Alguém algum lugar
fonte
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);
    }
}
EddieB
fonte
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());
matasoy
fonte
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());
Ahsan Raza
fonte
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();.
Samuh
fonte
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.

Valentin Galea
fonte
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 ;)

MBH
fonte
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í...

mOmO
fonte
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);
IT-Dan
fonte
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.

Mark Cramer
fonte
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í.

Dipendra
fonte
7

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

android:scrollbars="vertical"

E finalmente, adicione

textView.setMovementMethod(new ScrollingMovementMethod());

no arquivo Java.

user3921740
fonte
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.

android.weasel
fonte
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"
Raluca Lucaci
fonte
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);
Rahul Baradia
fonte
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());
}
Justin Buser
fonte
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());
Ritesh
fonte
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); 
Pérola Branca
fonte
2
yourtextView.setMovementMethod(new ScrollingMovementMethod());

você pode rolar agora.

Exutic
fonte
1
Isso é o que a resposta aceita já diz. Da revisão .
Wai Ha Lee
1

Use-o assim

<TextView  
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:maxLines = "AN_INTEGER"
    android:scrollbars = "vertical"
/>
Kamil Ibadov
fonte
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"
Sasha 888
fonte
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

Petro
fonte
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());

Khemraj
fonte
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;
            }
        });
Rohit Mandiwal
fonte
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

Principe
fonte
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)

cerquilha
fonte
0

Tente o seguinte:

android:scrollbars = "vertical"
mohamad sheikhi
fonte