Liczba aktywnych znaków w EditText

103

Zastanawiałem się, jaki najlepszy sposób na liczenie znaków w polu edycji na żywo jest w systemie Android. Patrzyłem na to, ale nie mogłem tego zrozumieć.

Aby opisać problem, mam EditText i próbuję ograniczyć liczbę znaków do 150. Mogę to zrobić za pomocą filtru wejściowego, jednak chcę pokazać tuż pod polem tekstowym liczbę znaków, które wprowadził użytkownik (Prawie tak jak przepełnienie stosu robi się teraz).

Gdyby ktoś mógł napisać mały fragment przykładowego kodu lub wskazać mi właściwy kierunek, byłbym bardzo wdzięczny.

Taylor Perkins
źródło

Odpowiedzi:

154

możesz użyć TextWatchera, aby zobaczyć, kiedy tekst się zmienił

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

ustawiasz TextWatcher dla edittext za pomocą

mEditText.addTextChangedListener(mTextEditorWatcher);
Cameron Ketcham
źródło
5
próbował tego, działa świetnie! powinna być wybrana jako poprawna odpowiedź!
Patrick Boos,
2
jaki byłby najlepszy sposób dodania liczby, powiedz w prawym dolnym rogu pola tekstowego. Rozszerzyć tekst edycji i ręcznie narysować ciąg?
Niedźwiedź
1
Dzięki, też to rozumiem, ale jak uzyskać odliczanie w odwrotnej kolejności, np. 150,149,148,147 ... podczas wpisywania tekstu.
vinay Maneti
6
Rozwiązano go, zastępując tym wierszem mTextView.setText (String.valueOf (150-s.length ())); zamiast mTextView.setText (String.valueOf (s.length ()));
vinay Maneti
Mój problem jest podobny do tego, który ma @Bear. Muszę pokazać ten odliczany tekst tuż pod tekstem edycji. Każdy ma coś do udostępnienia w tym dokumencie. Dzięki.
Suresh Sharma
108

Możesz zliczać znaki z samego xml za pomocą opakowania TextInputLayout dla EditText wprowadzonego w SupportLibrary v23.1

Po prostu zawiń EditText za pomocą TextInputLayout i ustaw CounterEnabled na true i ustaw 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>

Dostaniesz istotny wpływ jak to

Możesz użyć counterOverflowTextAppearance , counterTextAppearance, aby nadać styl licznikowi.

EDYTOWAĆ

Z dokumentacji Androida.

TextInputEditText klasa jest do stosowania jako dziecko tego układu. Użycie TextInputEditText umożliwia TextInputLayout większą kontrolę nad wizualnymi aspektami dowolnego wprowadzania tekstu. Przykładowe użycie jest następujące:

     <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
źródło
3
to było dokładnie to, czego szukałem :) czysty, pomocniczy plik impl. dzięki
VPZ
3
Powinna być zaakceptowana odpowiedź! Tęskniłem za tymi atrybutami!
sud007
25

Możesz to zrobić za pomocą TextInputLayoutbibliotek kompatybilnych z:

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

i uzupełnij:

<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
źródło
Świetnie to zadziałało, ale jak zmienić kolor licznika?
Erich García
14

w xml dodaj ten atrybut do editText

    android:maxLength="80"

w java dodaj ten odbiornik

  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
źródło
7

To bardzo proste Postępuj zgodnie z poniższymi instrukcjami:

==== Dodaj je do swoich importów ===

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

===== Zdefiniuj to =====

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
źródło
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
źródło
Dzięki @RavishSharma :) Doceniam twój komentarz.
Rana Pratap Singh
4

Po prostu ustaw te 2 linie TextInputLayoutw swoim pliku XML:

app:counterEnabled="true"
app:counterMaxLength="200"
mortezahosseini
źródło
Great o tym nie wiedział. Wydaje się, że zawsze lepszym rozwiązaniem jest zawinięcie Edittext w TextInputLayout.
Stefan Sprenger
3

To rozwiązanie używa Kotlini pokazuje liczbę pozostałych znaków. Ponadto, jeśli aktualna liczba znaków przekroczy limit 50, kolor tekstu zmieni się na czerwony.

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

Nie zapomnij też dodać TextWatcherdo swojegoEditText

YOUR_EDIT_TEXT_ID.addTextChangedListener(mTitleTextWatcher)
grantespo
źródło
3

Możesz dodać licznik do swojego TextInputEditText, który jest zawijany w TextInputLayout. Jak widać na przykładzie, counterEnabledwłącza tę funkcję i counterMaxLenghokreśla dla niej liczbę znaków.

<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
źródło
2

Spotkałem ten sam problem i wypróbowałem metodę Camerona. Działa, ale jest drobny błąd: jeśli użytkownik użyje kopiuj i wklej, nie policzy znaków. Proponuję więc zrobić po zmianie tekstu, jak poniżej:

    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
źródło
1

Użyj Androida: maxLength = "140"

To powinno działać. :)

Mam nadzieję, że to pomoże

Alireza Ghanbarinia
źródło
0

Spróbuj zrobić coś takiego.

To rozwiązanie może być bardziej wydajne niż uzyskiwanie CharSequence.length. Za każdym dotknięciem miękkiej klawiatury zdarzenie jest uruchamiane; dlatego jeśli zrobisz długość, za każdym razem policzy CharSequence, co może spowolnić, jeśli zaczniesz wchodzić w duże CharSequnces. Odbiornik zdarzenia przy zmianie tekstu ustawia licznik przed i po. Działa to dobrze w przypadku wartości zwiększania i zmniejszania

@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
źródło
to jest efekt permosrmatce, TextWatcher jest najlepszym podejściem do tego
Naveed Ahmad
0

Spróbuj tego

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
źródło
0

Przejrzysta droga;

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
źródło