2013-08-30 8 views
13

Próbuję zaimplementować EditText, który ogranicza również dane wejściowe tylko do znaków Capital [A-Z0-9] z cyframi.Filtr wejściowy w EditText powoduje powtarzanie tekstu

zacząłem metodą InputFilter od jakiegoś post.But tutaj jestem coraz jeden problem na Samsung Galaxy Tab 2, ale nie w emulatorze lub Nexus 4.

Problem jest tak:

  1. Kiedy Wpisuję "A" tekst pokazuje jako "A" jego dobry
  2. Teraz gdy wpisuję "B", tekst powinien brzmieć "AB", ale daje mi "AAB" to wygląda bardzo dziwnie.

Krótko powtarza znaków

Oto kod pracuję z tym kodem: Kod plik

public class DemoFilter implements InputFilter { 

    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, 
      int dend) { 

     if (source.equals("")) { // for backspace 
      return source; 
     } 
     if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints 
                 // here 
     { 
      return source.toString().toUpperCase(); 
     } 
     return ""; 
    } 
} 

XML:

<EditText 
    android:id="@+id/et_licence_plate_1" 
    android:layout_width="0dp" 
    android:layout_height="wrap_content" 
    android:layout_weight="3" 
    android:hint="0" 
    android:imeOptions="actionNext" 
    android:inputType="textNoSuggestions" 
    android:maxLength="3" 
    android:singleLine="true" 
    android:textSize="18px" > 
</EditText> 

jestem całkowicie zatrzymany w górę na tej, więc wszelka pomoc tutaj będzie bardzo ceniona.

Odpowiedz

1

InputFilters może być dołączony do edycji S, aby ograniczyć zmiany, które mogą być wykonane do nich. Patrz, że kładzie nacisk na zmiany wprowadzone zamiast całego tekstu zawiera ona ..

Wykonaj wymienione poniżej ...

public class DemoFilter implements InputFilter { 

     public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, 
       int dend) { 

      if (source.equals("")) { // for backspace 
       return source; 
      } 
      if (source.toString().matches("[a-zA-Z0-9 ]*")) // put your constraints 
                  // here 
      { 
       char[] ch = new char[end - start]; 

       TextUtils.getChars(source, start, end, ch, 0); 

       // make the characters uppercase 
       String retChar = new String(ch).toUpperCase(); 
       return retChar; 
      } 
      return ""; 
     } 
    } 
+0

podziękowania dla naszej odpowiedzi, Pozwól mi sprawdzić to działa, czy nie? –

+0

Nie działa –

+0

Huh, sprawdziłem tutaj opublikowany kod i jego działanie zgodnie z oczekiwaniami, możesz również opublikować implementację pliku XML swojego edytowalnego tekstu, w którym dodajesz ten DemoFilter .. – CRUSADER

0

spróbuj tego:

class CustomInputFilter implements InputFilter { 
    StringBuilder sb = new StringBuilder(); 

    @Override 
    public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
     Log.d(TAG, "filter " + source + " " + start + " " + end + " dest " + dest + " " + dstart + " " + dend); 
     sb.setLength(0); 
     for (int i = start; i < end; i++) { 
      char c = source.charAt(i); 
      if (Character.isUpperCase(c) || Character.isDigit(c) || c == ' ') { 
       sb.append(c); 
      } else 
      if (Character.isLowerCase(c)) { 
       sb.append(Character.toUpperCase(c)); 
      } 
     } 
     return sb; 
    } 
} 

ten umożliwia również filtrowanie gdy jest filtr Metoda() akceptuje wiele znaków naraz, np wklejony tekst ze schowka

8

Problem duplikacji postaci pochodzi ze złej implementacji InputFilter. Raczej zwróci null jeśli wymiana nie powinna ulec zmianie:

@Override 
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { 
    boolean keepOriginal = true; 
    StringBuilder sb = new StringBuilder(end - start); 
    for (int i = start; i < end; i++) { 
     char c = source.charAt(i); 
     if (isCharAllowed(c)) // put your condition here 
      sb.append(c); 
     else 
      keepOriginal = false; 
    } 
    if (keepOriginal) 
     return null; 
    else { 
     if (source instanceof Spanned) { 
      SpannableString sp = new SpannableString(sb); 
      TextUtils.copySpansFrom((Spanned) source, start, end, null, sp, 0); 
      return sp; 
     } else { 
      return sb; 
     }   
    } 
} 

private boolean isCharAllowed(char c) { 
    return Character.isUpperCase(c) || Character.isDigit(c); 
} 
+0

To jest poprawne. Zobacz implementację InputFilter.AllCaps, która kopiuje tekst wyniku, jak pokazano tutaj. –

+2

Możesz wypróbować Androida: inputType = "textVisiblePassword", aby wyłączyć autouzupełnianie, co jest prawdziwym problemem dla filtru wejściowego. Nie byłby to właściwy sposób, ale po prostu działa. Twoje zdrowie! –

+0

Twoje rozwiązanie działa! Trzeba tylko pamiętać, że ten problem pojawia się tylko na Androidzie 7, ale nie na systemie Android 6 lub Android 8 (przynajmniej dla mojej aplikacji). –

1

Zabrakło mi do tego samego problemu, po zamontowaniu go z rozwiązań zamieszczonych tutaj nie było jeszcze pozostały problem z klawiatur z autouzupełniania. Jednym z rozwiązań jest ustawienie inputType jako "visiblePassword", ale to zmniejsza funkcjonalność, prawda?

udało mi się naprawić rozwiązania w drodze, po powrocie niezerowym wynik w metodzie filter(), użyj połączenia

TextUtils.copySpansFrom((Spanned) source, start, newString.length(), null, newString, 0); 

Kopiuje autouzupełniania przęsła do nowego związku i naprawia dziwne zachowanie powtórzeń podczas wybierania podpowiedzi autouzupełniania.

+0

Dzięki temu, skopiowanie Spans rozwiązało to dla mnie, ale to powodowało awarię mojej aplikacji, ponieważ 'źródło' nie zawsze było' Spanned'. Tak więc moje rozwiązanie to: 'jeśli (źródło instanceof Spanned) { \t TextUtils.copySpansFrom ((Spanned) source, start, newString.length(), null, newString, 0); \t } return newString; ' – Robyer

2

Znalazłem wiele błędów w filtrze InputFilter systemu Android, nie jestem pewien, czy są to błędy, czy też są tak zamierzone. Ale zdecydowanie nie spełniało moich wymagań.Więc zdecydowałem się użyć TextWatcher zamiast InputFilter

private String newStr = ""; 

myEditText.addTextChangedListener(new TextWatcher() { 
     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
      // Do nothing 
     } 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      String str = s.toString(); 
      if (str.isEmpty()) { 
       myEditText.append(newStr); 
       newStr = ""; 
      } else if (!str.equals(newStr)) { 
       // Replace the regex as per requirement 
       newStr = str.replaceAll("[^A-Z0-9]", ""); 
       myEditText.setText(""); 
      } 
     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      // Do nothing 
     } 
    }); 

Powyższy kod nie pozwalają użytkownikom wpisywać żadnego specjalnego symbolu do swojej EditText. Dozwolone są tylko duże alfanumeryczne znaki.

0

Poniższy Rozwiązanie obsługuje również opcję klawiaturze autouzupełniania

editTextFreeNote.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) { 
      String newStr = s.toString(); 
      newStr = newStr.replaceAll("[a-zA-Z0-9 ]*", ""); 
      if(!s.toString().equals(newStr)) { 
       editTextFreeNote.setText(newStr); 
       editTextFreeNote.setSelection(editTextFreeNote.getText().length()); 
      } 
     } 

     @Override 
     public void afterTextChanged(Editable s) {} 
    });