Yanıtlar:
Bunu başka bir forumda buldum. Bir şampiyon gibi çalışır.
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özlük önerilerini görüntüleyen Android sürümlerinde biraz karmaşıktır. Bazen bir olsun SpannableStringBuilder
, bazen sade String
içinde source
parametresi.
Devamındaki InputFilter
çalışması gerekir. Bu kodu geliştirmekten çekinmeyin!
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
girerken önceki cevabı denerken bana AAB'yi verir . Neyse ki aşağıdaki @florian çözümünü kullanarak bu sorunu çözebildim.
daha kolay:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
Aralarında vermek zorunda değilsiniz . Böyle bir şey kullanabilirsiniz"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
, vb.
Gönderilen cevapların hiçbiri benim için işe yaramadı. Kendi çözümümle geldim:
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
kendi filtrelerine sahip olabilir, örneğin uzunluk filtresi. Bu nedenle, filtreleri geçersiz kılmak yerine, büyük olasılıkla filtrelerinizi zaten mevcut olanlara eklemek istersiniz.
Bu işi% 100 ihtiyaç ve çok basit kullanın.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
Strings.xml dosyasında
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Giriş türünde Özel Karakterlerden kaçınmak için
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;
}
};
Düzenleme metninize aşağıdaki gibi filtre ayarlayabilirsiniz
edtText.setFilters(new InputFilter[] { filter });
Kabul edilen cevaba ek olarak, sadece büyük harf karakterleri (ve sayıları) kabul etmek için örneğin: özelliği android:inputType="textCapCharacters"
olarak da kullanılabilir <EditText>
.
Herhangi bir nedenle android.text.LoginFilter sınıfının yapıcısı paket kapsamlıdır, bu nedenle doğrudan genişletemezsiniz (bu kodla aynı olsa bile). Ancak LoginFilter.UsernameFilterGeneric! Sonra sadece bu var:
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;
}
}
Bu gerçekten belgelenmemiştir, ancak çekirdek lib'in bir parçasıdır ve kaynak basittir . Bir süredir kullanıyorum, şimdiye kadar sorun yok, ancak spannable'ları içeren karmaşık bir şey yapmayı denemediğimi itiraf ediyorum.
Doğru, bunu kullanarak XML Düzeninde düzeltmek için en iyi yol:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Florian Fröhlich'in haklı olarak işaret ettiği gibi, metin görünümleri için bile iyi çalışıyor.
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Dikkatli bir kelime, belirtilen karakterler android:digits
sadece görüntülenecektir, bu yüzden herhangi bir karakter kümesini kaçırmamaya dikkat edin :)
inputType
filtrelemeyi etkilemez.
Kullanıcının bir EditText içine boş dizeler girmesini önlemek gerektiğinde bu basit çözüm benim için çalıştı. Elbette daha fazla karakter ekleyebilirsiniz:
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});
}
InputFilter alt sınıfını yaparsanız, alfasayısal olmayan karakterleri filtreleyecek kendi InputFilter öğenizi oluşturabilirsiniz.
InputFilter Arabirimi'nin bir yöntemi vardır filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
ve size hangi karakterlerin atandığı EditText'e girildiğiyle ilgili bilmeniz gereken tüm bilgileri sağlar.
Kendi InputFilter öğenizi oluşturduktan sonra, setFilters (...) öğesini çağırarak Filtreyi EditText'e atayabilirsiniz.
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text.Spanned, int, int)
Diğer insanların uğraştığı span şeylerini göz ardı ederek, sözlük önerilerini doğru bir şekilde işlemek için aşağıdaki kod çalışmalarını buldum.
Öneri büyüdükçe kaynak büyüyor, bu yüzden herhangi bir şeyi iade etmeden önce aslında kaç karakter bizi değiştirmemizi beklediğine bakmalıyız.
Geçersiz karakterimiz yoksa, varsayılan değiştirmenin gerçekleşmesi için null değerini döndürün.
Aksi takdirde, GERÇEKTEN EditText'e yerleştirilecek olan alt dizeden geçerli karakterleri çıkarmamız gerekir.
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;
}
};
edittext'de kelimeleri önlemek için. u istediğiniz zaman kullanabileceğiniz bir sınıf oluşturun.
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;
}
}
Önce şunu ekleyin strings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
Kotlin'de Kod :
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
}
Garip, ama emülatörün yumuşak klavyesinde garip bir şekilde çalışıyor.
Uyarı! Aşağıdaki kod, yazılım klavyelerinin rakamları dışındaki tüm harfleri ve diğer simgeleri filtreleyecektir. Akıllı telefonlarda yalnızca dijital klavye görünecektir.
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Ben de genellikle set maxLength
, filters
, inputType
.
Bu eski bir iş parçacığıdır, ancak amaçlanan çözümlerin hepsinin sorunları vardır (cihaza / Android sürümüne / Klavyeye bağlı olarak).
FARKLI YAKLAŞIM
Yani sonuçta ben kullanmak yerine, farklı bir yaklaşımla gitti InputFilter
, sorunlu uygulanmasını kullanıyorum TextWatcher
ve TextChangedListener
bir EditText
.
TAM KOD (ÖRNEK)
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
}
});
Nedeni InputFilter
, Android'de iyi bir çözüm değildir, çünkü klavye uygulamasına bağlıdır. Klavye girişi, girişe geçirilmeden önce filtreleniyor EditText
. Ancak, bazı klavyelerin InputFilter.filter()
çağırma için farklı uygulamaları olduğundan , bu sorunludur.
Öte yandan TextWatcher
klavye uygulamasını önemsemiyor, basit bir çözüm oluşturmamıza ve tüm cihazlarda çalışacağından emin olmamıza izin veriyor.
onTextChanged
Sadece ihtiyacı public void
o cepheyi.
Basit tutmak için böyle bir şey yaptım:
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 ]"), "")
}
})
Bu şekilde, kaynak dizenin yeni bölümündeki tüm istenmeyen karakterleri boş bir dizeyle değiştiriyoruz.
edit_text
Değişkendir EditText
Peki bahsettiğimiz nesnesi.
Kod yazılmıştır kotlin
.
Kullanmak mümkündür setOnKeyListener
. Bu yöntemde girişi özelleştirebiliriz edittext
!
Metni Düzenle'deki Ad alanı için filtreyi bu şekilde oluşturdum. (İlk harf CAPS'tir ve her sözcükten sonra yalnızca tek bir boşluğa izin verir.
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)});
}
Kotlin'de de aynı cevabım var:
/**
* 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
}
}
}
ve bir eklenti işleviyle sınıfı edinin:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}