Antworten:
Ich habe das in einem anderen Forum gefunden. Funktioniert wie ein Champion.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (!Character.isLetterOrDigit(source.charAt(i))) {
return "";
}
}
return null;
}
};
edit.setFilters(new InputFilter[] { filter });
InputFilter
s sind in Android-Versionen, in denen Wörterbuchvorschläge angezeigt werden, etwas kompliziert. Manchmal erhalten Sie eine SpannableStringBuilder
, manchmal eine Ebene String
im source
Parameter.
Folgendes InputFilter
sollte funktionieren. Fühlen Sie sich frei, diesen Code zu verbessern!
new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
if (source instanceof SpannableStringBuilder) {
SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder)source;
for (int i = end - 1; i >= start; i--) {
char currentChar = source.charAt(i);
if (!Character.isLetterOrDigit(currentChar) && !Character.isSpaceChar(currentChar)) {
sourceAsSpannableBuilder.delete(i, i+1);
}
}
return source;
} else {
StringBuilder filteredStringBuilder = new StringBuilder();
for (int i = start; i < end; i++) {
char currentChar = source.charAt(i);
if (Character.isLetterOrDigit(currentChar) || Character.isSpaceChar(currentChar)) {
filteredStringBuilder.append(currentChar);
}
}
return filteredStringBuilder.toString();
}
}
}
String replacement = source.subSequence(start, end).toString(); return replacement.replaceAll("[^A-Za-z0-9_\\-@]", "");
source instanceof SpannableStringBuilder
Eingabe von AB AAB, wie wenn ich die vorherige Antwort versuche. Glücklicherweise konnte ich es mithilfe der folgenden @ florian-Lösung umgehen.
viel einfacher:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
dazwischen geben. Sie können so etwas verwenden"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
usw.
Keine der geposteten Antworten hat bei mir funktioniert. Ich kam mit meiner eigenen Lösung:
InputFilter filter = new InputFilter() {
@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, sb.length(), null, sp, 0);
return sp;
} else {
return sb;
}
}
}
private boolean isCharAllowed(char c) {
return Character.isLetterOrDigit(c) || Character.isSpaceChar(c);
}
}
editText.setFilters(new InputFilter[] { filter });
EditText
bereits eigene Filter haben kann, zB Längenfilter. Anstatt nur die Filter zu überschreiben, möchten Sie Ihre Filter höchstwahrscheinlich zu bereits vorhandenen hinzufügen.
Verwenden Sie dies seine Arbeit 100% Ihre Bedürfnisse und sehr einfach.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
In strings.xml
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Um Sonderzeichen im Eingabetyp zu vermeiden
public static InputFilter filter = new InputFilter() {
@Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String blockCharacterSet = "~#^|$%*!@/()-'\":;,?{}=!$^';,?×÷<>{}€£¥₩%~`¤♡♥_|《》¡¿°•○●□■◇◆♧♣▲▼▶◀↑↓←→☆★▪:-);-):-D:-(:'(:O 1234567890";
if (source != null && blockCharacterSet.contains(("" + source))) {
return "";
}
return null;
}
};
Sie können den Filter wie unten beschrieben auf Ihren Bearbeitungstext einstellen
edtText.setFilters(new InputFilter[] { filter });
Zusätzlich zur akzeptierten Antwort ist es auch möglich, zB: android:inputType="textCapCharacters"
als Attribut von <EditText>
zu verwenden, um nur Großbuchstaben (und Zahlen) zu akzeptieren.
Aus irgendeinem Grund ist der Konstruktor der android.text.LoginFilter-Klasse paketbasiert, sodass Sie ihn nicht direkt erweitern können (obwohl er mit diesem Code identisch wäre). Sie können LoginFilter.UsernameFilterGeneric jedoch erweitern! Dann haben Sie einfach Folgendes:
class ABCFilter extends LoginFilter.UsernameFilterGeneric {
public UsernameFilter() {
super(false); // false prevents not-allowed characters from being appended
}
@Override
public boolean isAllowed(char c) {
if ('A' <= c && c <= 'C')
return true;
if ('a' <= c && c <= 'c')
return true;
return false;
}
}
Dies ist nicht wirklich dokumentiert, aber es ist Teil der Kernbibliothek und die Quelle ist unkompliziert . Ich benutze es jetzt schon eine Weile, bisher keine Probleme, obwohl ich zugeben muss, dass ich nichts Komplexes mit spannables versucht habe.
Es ist richtig, der beste Weg, dies im XML-Layout selbst zu beheben, indem Sie Folgendes verwenden:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Wie Florian Fröhlich zu Recht betont, eignet es sich auch gut für Textansichten.
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Nur ein Wort der Vorsicht, die in der genannten Zeichen android:digits
werden nur angezeigt. Achten Sie also darauf, dass Sie keine Zeichen verpassen :)
inputType
dies keinen Einfluss auf die Filterung.
Diese einfache Lösung funktionierte für mich, als ich verhindern musste, dass der Benutzer leere Zeichenfolgen in einen EditText eingibt. Sie können natürlich weitere Zeichen hinzufügen:
InputFilter textFilter = new InputFilter() {
@Override
public CharSequence filter(CharSequence c, int arg1, int arg2,
Spanned arg3, int arg4, int arg5) {
StringBuilder sbText = new StringBuilder(c);
String text = sbText.toString();
if (text.contains(" ")) {
return "";
}
return c;
}
};
private void setTextFilter(EditText editText) {
editText.setFilters(new InputFilter[]{textFilter});
}
Wenn Sie InputFilter unterordnen, können Sie Ihren eigenen InputFilter erstellen, der alle nicht alphanumerischen Zeichen herausfiltert.
Die InputFilter-Schnittstelle verfügt über eine Methode: filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
und bietet Ihnen alle Informationen, die Sie benötigen, um zu wissen, welche Zeichen in den EditText eingegeben wurden, dem sie zugewiesen sind.
Nachdem Sie Ihren eigenen InputFilter erstellt haben, können Sie ihn dem EditText zuweisen, indem Sie setFilters (...) aufrufen.
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text.Spanned, int, int)
Ich ignorierte das Span-Zeug, mit dem sich andere Leute befasst haben, um Wörterbuchvorschläge richtig zu handhaben. Ich fand, dass der folgende Code funktioniert.
Die Quelle wächst mit dem Vorschlag, daher müssen wir uns ansehen, wie viele Zeichen wir tatsächlich ersetzen sollen, bevor wir etwas zurückgeben.
Wenn wir keine ungültigen Zeichen haben, geben Sie null zurück, damit die Standardersetzung erfolgt.
Andernfalls müssen wir die gültigen Zeichen aus dem Teilstring extrahieren, der tatsächlich in den EditText eingefügt wird.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
boolean includesInvalidCharacter = false;
StringBuilder stringBuilder = new StringBuilder();
int destLength = dend - dstart + 1;
int adjustStart = source.length() - destLength;
for(int i=start ; i<end ; i++) {
char sourceChar = source.charAt(i);
if(Character.isLetterOrDigit(sourceChar)) {
if(i >= adjustStart)
stringBuilder.append(sourceChar);
} else
includesInvalidCharacter = true;
}
return includesInvalidCharacter ? stringBuilder : null;
}
};
um Wörter in edittext zu verhindern. Erstelle eine Klasse, die du jederzeit verwenden kannst.
public class Wordfilter implements InputFilter
{
@Override
public CharSequence filter(CharSequence source, int start, int end,Spanned dest, int dstart, int dend) {
// TODO Auto-generated method stub
boolean append = false;
String text = source.toString().substring(start, end);
StringBuilder str = new StringBuilder(dest.toString());
if(dstart == str.length())
{
append = true;
str.append(text);
}
else
str.replace(dstart, dend, text);
if(str.toString().contains("aaaaaaaaaaaa/*the word here*/aaaaaaaa"))
{
if(append==true)
return "";
else
return dest.subSequence(dstart, dend);
}
return null;
}
}
Zuerst hinzufügen in strings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
Code in Kotlin:
edit_text.filters += InputFilter { source, start, end, _, _, _ ->
val mask = getString(R.string.vin_code_mask)
for (i in start until end) {
if (!mask.contains(source[i])) {
return@InputFilter ""
}
}
null
}
Seltsam, aber es funktioniert komisch auf der Softtastatur des Emulators.
Warnung! Der folgende Code filtert alle Buchstaben und anderen Symbole mit Ausnahme der Ziffern für Software-Tastaturen. Auf Smartphones wird nur die digitale Tastatur angezeigt.
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Ich habe auch in der Regel eingestellt maxLength
, filters
, inputType
.
Dies ist ein alter Thread, aber die beabsichtigten Lösungen haben alle Probleme (abhängig von Gerät / Android-Version / Tastatur).
VERSCHIEDENER ANSATZ
Also habe ich mich irgendwann für einen anderen Ansatz entschieden, anstatt die InputFilter
problematische Implementierung zu verwenden, die ich verwende, TextWatcher
und die TextChangedListener
der EditText
.
VOLLSTÄNDIGER CODE (BEISPIEL)
editText.addTextChangedListener(new TextWatcher() {
@Override
public void afterTextChanged(Editable editable) {
super.afterTextChanged(editable);
String originalText = editable.toString();
int originalTextLength = originalText.length();
int currentSelection = editText.getSelectionStart();
// Create the filtered text
StringBuilder sb = new StringBuilder();
boolean hasChanged = false;
for (int i = 0; i < originalTextLength; i++) {
char currentChar = originalText.charAt(i);
if (isAllowed(currentChar)) {
sb.append(currentChar);
} else {
hasChanged = true;
if (currentSelection >= i) {
currentSelection--;
}
}
}
// If we filtered something, update the text and the cursor location
if (hasChanged) {
String newText = sb.toString();
editText.setText(newText);
editText.setSelection(currentSelection);
}
}
private boolean isAllowed(char c) {
// TODO: Add the filter logic here
return Character.isLetter(c) || Character.isSpaceChar(c);
}
@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) {
// Do Nothing
}
});
Der Grund, warum InputFilter
Android keine gute Lösung ist, liegt darin, dass es von der Tastaturimplementierung abhängt. Die Tastatureingabe wird gefiltert, bevor die Eingabe an die übergeben wird EditText
. InputFilter.filter()
Dies ist jedoch problematisch , da einige Tastaturen unterschiedliche Implementierungen für den Aufruf haben.
Auf der anderen Seite TextWatcher
kümmert sich die Tastaturimplementierung nicht darum, sondern ermöglicht es uns, eine einfache Lösung zu erstellen und sicherzustellen, dass sie auf allen Geräten funktioniert.
onTextChanged
braucht einfach ein public void
davor.
Ich habe so etwas getan, um es einfach zu halten:
edit_text.filters = arrayOf(object : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {
return source?.subSequence(start, end)
?.replace(Regex("[^A-Za-z0-9 ]"), "")
}
})
Auf diese Weise ersetzen wir alle unerwünschten Zeichen im neuen Teil der Quellzeichenfolge durch eine leere Zeichenfolge.
Die edit_text
Variable ist dieEditText
Objekt, auf das wir uns beziehen.
Der Code ist in geschrieben kotlin
.
Es ist möglich zu verwenden setOnKeyListener
. In dieser Methode können wir die Eingabe anpassen edittext
!
Auf diese Weise habe ich einen Filter für das Feld Name in Text bearbeiten erstellt. (Der erste Buchstabe ist GROSSBUCHSTABEN. Nach jedem Wort darf nur ein Leerzeichen stehen.
public void setNameFilter() {
InputFilter filter = new InputFilter() {
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (dend == 0) {
if (Character.isSpaceChar(source.charAt(i)) ||
!Character.isAlphabetic(source.charAt(i))) {
return Constants.Delimiter.BLANK;
} else {
return String.valueOf(source.charAt(i)).toUpperCase();
}
} else if (Character.isSpaceChar(source.charAt(i)) &&
String.valueOf(dest).endsWith(Constants.Delimiter.ONE_SPACE)) {
return Constants.Delimiter.BLANK;
} else if ((!Character.isSpaceChar(source.charAt(i)) &&
!Character.isAlphabetic(source.charAt(i)))) {
return Constants.Delimiter.BLANK;
}
}
return null;
}
};
editText.setFilters(new InputFilter[]{filter, new InputFilter.LengthFilter(Constants.Length.NAME_LENGTH)});
}
Ich habe die gleiche Antwort in Kotlin:
/**
* Returns the filter of the editText'es CharSequence value when [filterType] is:
* 1 -> letters; 2 -> letters and digits; 3 -> digits;
* 4 -> digits and dots
*/
class InputFilterAlphanumeric(private val filterType: Int): InputFilter {
override fun filter(source: CharSequence?, start: Int, end: Int, dest: Spanned?, dstart: Int, dend: Int): CharSequence {
(source as? SpannableStringBuilder)?.let {sourceAsSpannableBuilder ->
for (i in (end - 1) downTo start) {
val currentChar = source[i]
when(filterType) {
1 -> {
if (!currentChar.isLetter() && !currentChar.isWhitespace()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
2 -> {
if (!currentChar.isLetterOrDigit() && !currentChar.isWhitespace()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
3 -> {
if (!currentChar.isDigit()) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
4 -> {
if (!currentChar.isDigit() || !currentChar.toString().contains(".")) {
sourceAsSpannableBuilder.delete(i, i + 1)
}
}
}
}
return source
} ?: run {
val filteredStringBuilder = StringBuilder()
for (i in start until end) {
val currentChar = source?.get(i)
when(filterType) {
1 -> {
if (currentChar?.isLetter()!! || currentChar.isWhitespace()) {
filteredStringBuilder.append(currentChar)
}
}
2 -> {
if (currentChar?.isLetterOrDigit()!! || currentChar.isWhitespace()) {
filteredStringBuilder.append(currentChar)
}
}
3 -> {
if (currentChar?.isDigit()!!) {
filteredStringBuilder.append(currentChar)
}
}
4 -> {
if (currentChar?.isDigit()!! || currentChar.toString().contains(".")) {
filteredStringBuilder.append(currentChar)
}
}
}
}
return filteredStringBuilder
}
}
}
und erhalten Sie die Klasse mit einer Erweiterungsfunktion:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}