Recuento de caracteres en vivo para EditText

101

Me preguntaba cuál es la mejor manera de hacer un recuento de caracteres en vivo de un cuadro de texto de edición en Android. Estaba mirando esto, pero parecía que no podía encontrarle ningún sentido.

Para describir el problema, tengo un EditText y estoy tratando de limitar los caracteres a 150. Puedo hacer esto con un filtro de entrada, sin embargo, quiero mostrar justo debajo del cuadro de texto la cantidad de caracteres que un usuario ha ingresado (Casi como está haciendo el desbordamiento de pila en este momento).

Si alguien pudiera escribir un pequeño fragmento de código de ejemplo o señalarme en la dirección correcta, lo agradecería mucho.

Taylor Perkins
fuente

Respuestas:

153

puede usar un TextWatcher para ver cuando el texto ha cambiado

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

configura el TextWatcher para el texto de edición con

mEditText.addTextChangedListener(mTextEditorWatcher);
Cameron Ketcham
fuente
5
probado esto, funciona muy bien! debe seleccionarse como respuesta correcta!
Patrick Boos
2
cuál sería la mejor manera de agregar el recuento, diga en la parte inferior derecha del cuadro de texto. ¿Extender editar texto y dibujar la cadena manualmente?
Bear
1
Gracias, yo también lo entendí, pero cómo obtener la cuenta regresiva en orden inverso como 150,149,148,147 ... mientras ingresa el texto.
vinay Maneti
6
Se solucionó reemplazando con esta línea mTextView.setText (String.valueOf (150-s.length ())); en lugar de mTextView.setText (String.valueOf (s.length ()));
vinay Maneti
Mi problema es similar al que tiene @Bear. Necesito mostrar este texto de cuenta atrás justo debajo del texto de edición. Cualquiera tiene algo que compartir en esta referencia. Gracias.
Suresh Sharma
107

Puede hacer el recuento de caracteres desde xml usando el contenedor TextInputLayout para EditText introducido en SupportLibrary v23.1

Simplemente envuelva su EditText con un TextInputLayout y establezca CounterEnabled en verdadero y establezca un 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>

Obtendrás un efecto material como este

Puede usar counterOverflowTextAppearance , counterTextAppearance para diseñar el contador.

EDITAR

De la documentación de Android.

La clase TextInputEditText se proporciona para usarse como un elemento secundario de este diseño. El uso de TextInputEditText permite a TextInputLayout un mayor control sobre los aspectos visuales de cualquier entrada de texto. Un ejemplo de uso es el siguiente:

     <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
fuente
3
esto era exactamente lo que estaba buscando :) una implícita biblioteca de soporte limpia. gracias
VPZ
3
¡Debería ser la respuesta aceptada! ¡Extrañé totalmente esos atributos!
sud007
24

Puede hacerlo TextInputLayouty compatibilizar bibliotecas con:

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

y completar:

<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 Gómez Rico
fuente
Genial, esto funcionó para mí, pero ¿cómo cambio el color del mostrador?
Erich García
14

en xml agregue este atributo para editText

    android:maxLength="80"

en java agregue este oyente

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

Es muy simple Siga las instrucciones a continuación:

==== Agrégalos a tus importaciones ===

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

===== Defina esto =====

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
fuente
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
fuente
Gracias @RavishSharma :) Agradezco tu comentario.
Rana Pratap Singh
4

Simplemente configure estas 2 líneas TextInputLayouten su archivo XML:

app:counterEnabled="true"
app:counterMaxLength="200"
mortezahosseini
fuente
Great no sabía nada de eso. Siempre parece ser la mejor solución envolver un Edittext en un TextInputLayout.
Stefan Sprenger
3

Esta solución usa Kotliny muestra el número de caracteres que quedan. Además, si el número actual de caracteres supera el límite de 50, el color del texto cambiará a rojo.

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) {}
}

Además, no olvide agregar el TextWatchera suEditText

YOUR_EDIT_TEXT_ID.addTextChangedListener(mTitleTextWatcher)
grantespo
fuente
3

Puede agregar un contador a su TextInputEditText envuelto en un TextInputLayout. Como puede ver en el ejemplo, counterEnabledhabilita esta función y counterMaxLenghdefine la cantidad de caracteres para ella.

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

Me encontré con el mismo problema y probé el método de Cameron. Funciona, pero hay un error menor: si el usuario usa copiar y pegar, no podrá contar los caracteres. Así que sugiero hacerlo después de que el texto cambie, como a continuación:

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

Utilice android: maxLength = "140"

Eso debería funcionar. :)

Espero que ayude

Alireza Ghanbarinia
fuente
0

Intente hacer algo como esto.

Esta solución puede ser más eficaz en lugar de obtener CharSequence.length. Cada vez que toca en el teclado virtual, se activa el evento; por lo tanto, si hace una longitud, contará la secuencia de caracteres cada vez, lo que puede ralentizarse si comienza a obtener secuencias de caracteres grandes. El oyente de eventos en el cambio de texto incluye el recuento antes y después. Esto funciona bien para valores de incremento y 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));
            }
        }
Víctor J. García
fuente
esto es efecto permosrmatce, TextWatcher es el mejor enfoque para esto
Naveed Ahmad
0

prueba esto

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

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