Contagem de caracteres ao vivo para EditText

101

Eu queria saber qual é a melhor maneira de fazer uma contagem de caracteres ao vivo de uma caixa de texto de edição no Android. Eu estava olhando para isso, mas não conseguia entender.

Para descrever o problema, tenho um EditText e estou tentando limitar os caracteres a 150. Posso fazer isso com um filtro de entrada, no entanto, quero mostrar logo abaixo da caixa de texto o número de caracteres que um usuário inseriu (quase como o estouro de pilha está fazendo agora).

Se alguém pudesse escrever um pequeno trecho de código de exemplo ou me apontar na direção certa, eu agradeceria muito.

Taylor Perkins
fonte

Respostas:

153

você pode usar um TextWatcher para ver quando o texto mudou

private TextView mTextView;
private EditText mEditText;
private final TextWatcher mTextEditorWatcher = new TextWatcher() {
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        public void onTextChanged(CharSequence s, int start, int before, int count) {
           //This sets a textview to the current length
           mTextView.setText(String.valueOf(s.length()));
        }

        public void afterTextChanged(Editable s) {
        }
};

você define o TextWatcher para o texto de edição com

mEditText.addTextChangedListener(mTextEditorWatcher);
Cameron Ketcham
fonte
5
tentei isso, funciona muito bem! deve ser selecionada como resposta correta!
Patrick Boos
2
qual seria a melhor maneira de adicionar a palavra de contagem no canto inferior direito da caixa de texto. Estender o texto de edição e desenhar a string manualmente?
Bear
1
Obrigado, eu também entendi, mas como obter a contagem regressiva em ordem reversa, como 150.149.148.147 ... ao inserir o texto.
vinay Maneti
6
Resolvido substituindo por esta linha mTextView.setText (String.valueOf (150-s.length ())); no lugar de mTextView.setText (String.valueOf (s.length ()));
vinay Maneti
Meu problema é semelhante ao do @Bear. Preciso mostrar esse texto de contagem regressiva logo abaixo do texto de edição. Alguém tem algo a compartilhar nesta referência. Obrigado.
Suresh Sharma
107

Você pode fazer contagem de caracteres a partir do próprio xml usando o wrapper TextInputLayout para EditText introduzido no SupportLibrary v23.1

Basta envolver seu EditText com um TextInputLayout e definir CounterEnabled como true e definir um counterMaxLength.

<android.support.design.widget.TextInputLayout
    android:id="@+id/textContainer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:counterEnabled="true"
    app:counterMaxLength="20"
    >
    <EditText
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Text Hint"
        />
</android.support.design.widget.TextInputLayout>

Você obterá um efeito material como este

Você pode usar counterOverflowTextAppearance , counterTextAppearance para definir o estilo do contador.

EDITAR

Da documentação do Android.

A classe TextInputEditText é fornecida para ser usada como filho desse layout. O uso de TextInputEditText permite a TextInputLayout maior controle sobre os aspectos visuais de qualquer entrada de texto. Um exemplo de uso é assim:

     <android.support.design.widget.TextInputLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content">

     <android.support.design.widget.TextInputEditText
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:hint="@string/form_username"/>

 </android.support.design.widget.TextInputLayout>

TextInputLayout TextInputEditText

Midhun Vijayakumar
fonte
3
isso era exatamente o que eu estava procurando :) um impl limpo de biblioteca de suporte. obrigado
VPZ
3
Deve ser a resposta aceita! Eu perdi totalmente esses atributos!
sud007
24

Você pode fazer isso com TextInputLayoutbibliotecas e compat com:

app:counterEnabled="true"
app:counterMaxLength="420"

e completo:

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:counterEnabled="true"
    app:counterMaxLength="420">

    <EditText
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:maxLength="420" />

</android.support.design.widget.TextInputLayout>
Daniel Gomez Rico
fonte
Ótimo, isso funcionou para mim, mas como eu mudo a cor do balcão?
Erich García
14

em xml adicione este atributo para editText

    android:maxLength="80"

em java adicione este ouvinte

  ed_caption.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            tv_counter.setText(80 - s.toString().length() + "/80");

        }
    });
Amal Kronz
fonte
7

É muito simples. Siga as instruções abaixo:

==== Adicione-os às suas importações ===

import android.text.Editable;
import android.text.TextWatcher;

===== Defina isto =====

private TextView sms_count;

========== Inside On Create =====

sms_count = (TextView) findViewById(R.id.textView2);


final TextWatcher txwatcher = new TextWatcher() {
   public void beforeTextChanged(CharSequence s, int start, int count, int after) {
   }

   public void onTextChanged(CharSequence s, int start, int before, int count) {

      sms_count.setText(String.valueOf(s.length()));
   }

   public void afterTextChanged(Editable s) {
   }
};

sms_message.addTextChangedListener(txwatcher);
Depinder Bharti
fonte
5
    You can use TextWatcher class to see text has changed and how much number of character remains.Here i have set counter of 140 characters.

    EditText typeMessageToPost;
    TextView number_of_character;
public void onCreate(Bundle savedBundleInstance) {
        super.onCreate(savedBundleInstance);
setContentView(R.layout.post_activity);
typeMessageToPost.addTextChangedListener(mTextEditorWatcher);
}
private final TextWatcher mTextEditorWatcher=new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // TODO Auto-generated method stub

        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count,
                int after) {
            // TODO Auto-generated method stub

        }

        @Override
        public void afterTextChanged(Editable s) {
            // TODO Auto-generated method stub
            number_of_character.setText(String.valueOf(140-s.length()));
        }
    };
Rana Pratap Singh
fonte
Obrigado @RavishSharma :) Agradeço seu comentário.
Rana Pratap Singh de
4

Basta definir estas 2 linhas TextInputLayoutem seu arquivo XML:

app:counterEnabled="true"
app:counterMaxLength="200"
mortezahosseini
fonte
Ótimo, não sabia disso. Parece sempre ser a melhor solução envolver um Edittext em um TextInputLayout.
Stefan Sprenger
3

Esta solução usa Kotline mostra o número de caracteres restantes. Além disso, se o número atual de caracteres ultrapassar o limite de 50, a cor do texto mudará para vermelho.

Kotlin

private val mTitleTextWatcher = object : TextWatcher {
    override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}

    override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
        if(YOUR_EDIT_TEXT_ID.text.toString().trim().length < 51){
            YOUR_CHAR_LEFT_TEXTVIEW_ID.text = (50 - YOUR_EDIT_TEXT_ID.text.toString().trim().length).toString()
            YOUR_CHAR_LEFT_TEXTVIEW_ID.setTextColor(Color.BLACK)
        }
        else{
            YOUR_CHAR_LEFT_TEXTVIEW_ID.text = "0"
            YOUR_CHAR_LEFT_TEXTVIEW_ID.setTextColor(Color.RED)
        }
    }

    override fun afterTextChanged(s: Editable) {}
}

Além disso, não se esqueça de adicionar TextWatcherao seuEditText

YOUR_EDIT_TEXT_ID.addTextChangedListener(mTitleTextWatcher)
grantespo
fonte
3

Você pode adicionar um contador ao TextInputEditText sendo encapsulado em um TextInputLayout. Como você pode ver no exemplo, counterEnabledhabilita esse recurso e counterMaxLenghdefine o número de caracteres para ele.

<com.google.android.material.textfield.TextInputLayout
        android:id="@+id/til_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:counterEnabled="true"
        app:counterMaxLength="50">
    <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/et_title"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
</com.google.android.material.textfield.TextInputLayout>
Sathish
fonte
1

Eu encontrei o mesmo problema e tentei o método de Cameron. Funciona, mas há um pequeno bug: se o usuário usar copiar e colar, não contará os caracteres. Então sugiro que faça após a alteração do texto, conforme abaixo:

    private final TextWatcher mTextEditorWatcher = new TextWatcher() {
         public void beforeTextChanged(CharSequence s, int start, int count, int after) {

         }

         public void onTextChanged(CharSequence s, int start, int before, int count) {

         }

          public void afterTextChanged(Editable s) {
             //This sets a textview to the current length
             mTextView.setText(String.valueOf(s.length()));
         }
    };
GilbertLee
fonte
1

Use android: maxLength = "140"

Isso deve funcionar. :)

espero que ajude

Alireza Ghanbarinia
fonte
0

Tente fazer algo assim.

Essa solução pode ter mais desempenho do que obter CharSequence.length. Cada vez que você toca no teclado virtual, o evento é disparado; portanto, se você fizer um comprimento, ele contará o CharSequence a cada vez, o que pode diminuir se você começar a obter grandes CharSequnces. O ouvinte de eventos na mudança de texto segue a contagem de antes e depois. Isso funciona bem para valores de incremento e decremento

@Override
        public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
            int tick = start + after;
            if(tick < mMessageMax) {
                int remaining = mMessageMax - tick;
                ((TextView)findViewById(R.id.contact_us_chars)).setText(String.valueOf(remaining));
            }
        }
Victor J. Garcia
fonte
este é o efeito permosrmatce, TextWatcher é a melhor abordagem para isso
Naveed Ahmad
0

tente isso

private TextWatcher textWatcher = new TextWatcher() {
    @Override
    public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) {
        editText.post(new Runnable() {
            @Override
            public void run() {
                if (length < 100) {
                    if (count > 0 && after <= 0)/*remove emoij*/ {
                        length--;
                    } else if (count > after)/*remove text*/ {
                        length--;
                    } else if (count == 0 && after > 1)/*emoij*/ {
                        ++length;
                    } else if (count == 0 && after == 1)/*Text*/ {
                        ++length;
                    } else if (count > 0 && after > 1) {
                        ++length;
                    }
                    if (s.length() <= 0)
                        length = 0;
                    Log.w("MainActivity", " Length: " + length);
                } else {
                    if (count > 0 && after <= 0)/*remove emoij*/ {
                        length--;
                    } else if (count > after)/*remove text*/ {
                        length--;
                    }
                    Log.w("MainActivity", " Length: " + length);
                }

                if (length == 100) {
                    editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(s.length())});
                } else {
                    editText.setFilters(new InputFilter[]{});
                }
            }
        });
    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {

    }
};

`

Nankai
fonte
0

Caminho claro;

abstract class CharacterWatcher : TextWatcher {
    override fun afterTextChanged(text: Editable?) {
        afterCharacterChanged(text?.lastOrNull(), text?.length)
    }

    override fun beforeTextChanged(text: CharSequence?, start: Int, count: Int, before: Int) {}

    override fun onTextChanged(text: CharSequence?, start: Int, before: Int, count: Int) {}

    abstract fun afterCharacterChanged(char: Char?, count: Int?)
}



 editText.addTextChangedListener(new CharacterWatcher() {
            @Override
            public void afterCharacterChanged(@Nullable Character character, @Nullable Integer count) {
                action()
            }
        });
Cafer Mert Ceyhan
fonte