Jawaban:
Saya menemukan ini di forum lain. Bekerja seperti jagoan.
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 agak rumit dalam versi Android yang menampilkan saran kamus. Anda terkadang mendapatkan SpannableStringBuilder
, terkadang polos String
di source
parameter.
Berikut ini InputFilter
harus bekerja. Jangan ragu untuk memperbaiki kode ini!
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
, memasuki AB memberi saya AAB seperti ketika mencoba jawaban sebelumnya. Untungnya saya bisa mengatasinya dengan menggunakan solusi @florian di bawah ini.
jauh lebih mudah:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
di antara keduanya. Anda dapat menggunakan sesuatu seperti ini"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
, dll.
Tidak ada jawaban yang diposting yang berfungsi untuk saya. Saya datang dengan solusi saya sendiri:
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
sudah dapat memiliki filter sendiri, mis. Filter panjang. Jadi, alih-alih hanya mengganti filter, Anda kemungkinan besar ingin menambahkan filter Anda ke yang sudah ada.
Gunakan ini kerjanya 100% kebutuhan Anda dan sangat sederhana.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
Di strings.xml
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Untuk menghindari Karakter Khusus dalam tipe input
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;
}
};
Anda dapat mengatur filter ke teks edit Anda seperti di bawah ini
edtText.setFilters(new InputFilter[] { filter });
Selain jawaban yang diterima, dimungkinkan juga untuk menggunakan misalnya: android:inputType="textCapCharacters"
sebagai atribut <EditText>
agar hanya menerima karakter huruf besar (dan angka).
Untuk beberapa alasan konstruktor kelas android.text.LoginFilter adalah paket-lingkup, sehingga Anda tidak dapat langsung memperpanjangnya (meskipun itu akan identik dengan kode ini). Tetapi Anda dapat memperpanjang LoginFilter.UsernameFilterGeneric! Maka Anda hanya memiliki ini:
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;
}
}
Ini tidak benar-benar didokumentasikan, tetapi itu adalah bagian dari inti lib, dan sumbernya langsung . Saya telah menggunakannya untuk sementara waktu sekarang, sejauh ini tidak ada masalah, meskipun saya akui saya belum mencoba melakukan sesuatu yang rumit yang melibatkan spannables.
Itu Benar, cara terbaik untuk memperbaikinya untuk memperbaikinya dalam Layout XML menggunakan:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
sebagaimana ditunjukkan oleh Florian Fröhlich, ini berfungsi dengan baik untuk tampilan teks yang rata.
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Hanya kata hati-hati, karakter yang disebutkan dalam android:digits
hanya akan ditampilkan, jadi berhati-hatilah untuk tidak melewatkan serangkaian karakter :)
inputType
tidak mempengaruhi pemfilteran.
Solusi sederhana ini bekerja untuk saya ketika saya perlu mencegah pengguna memasukkan string kosong ke dalam EditText. Tentu saja Anda dapat menambahkan lebih banyak karakter:
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});
}
Jika Anda subkelas InputFilter Anda dapat membuat InputFilter Anda sendiri yang akan memfilter karakter non-alfa-numerik.
InputFilter Interface memiliki satu metode,, filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
dan menyediakan Anda dengan semua informasi yang perlu Anda ketahui tentang karakter yang dimasukkan ke dalam EditText yang ditugaskan padanya.
Setelah Anda membuat InputFilter Anda sendiri, Anda dapat menetapkannya ke EditText dengan memanggil setFilters (...).
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text. Direncanakan, int, int)
Mengabaikan hal-hal rentang yang telah ditangani orang lain, untuk menangani saran kamus dengan benar, saya menemukan kode berikut berfungsi.
Sumber tumbuh seiring saran tumbuh sehingga kita harus melihat berapa banyak karakter yang sebenarnya diharapkan untuk kita ganti sebelum kita mengembalikan apa pun.
Jika kami tidak memiliki karakter yang tidak valid, kembalikan null sehingga terjadi penggantian default.
Kalau tidak, kita perlu mengekstraksi karakter yang valid dari substring yang SEBENARNYA akan ditempatkan ke dalam EditText.
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;
}
};
untuk mencegah kata-kata dalam edittext. buat kelas yang bisa Anda gunakan kapan saja.
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;
}
}
Pertama tambahkan strings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
Kode di 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
}
Aneh, tetapi bekerja aneh pada keyboard lunak emulator.
Peringatan! Kode berikut akan memfilter semua huruf dan simbol lainnya kecuali angka untuk keyboard perangkat lunak. Hanya keyboard digital yang akan muncul di smartphone.
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Saya juga biasanya ditetapkan maxLength
, filters
, inputType
.
Ini adalah utas lama, tetapi solusi yang dimaksudkan semuanya memiliki masalah (tergantung pada perangkat / versi Android / Keyboard).
PENDEKATAN YANG BERBEDA
Jadi akhirnya aku pergi dengan pendekatan yang berbeda, daripada menggunakan InputFilter
implementasi bermasalah, saya menggunakan TextWatcher
dan TextChangedListener
dari EditText
.
KODE LENGKAP (CONTOH)
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
}
});
Alasannya InputFilter
bukan solusi yang baik di Android karena itu tergantung pada implementasi keyboard. Input Keyboard sedang difilter sebelum input dilewatkan ke EditText
. Tetapi, karena beberapa keyboard memiliki implementasi yang berbeda untuk InputFilter.filter()
permohonan, ini bermasalah.
Di sisi lain TextWatcher
tidak peduli dengan implementasi keyboard, itu memungkinkan kami untuk membuat solusi sederhana dan memastikan itu akan bekerja pada semua perangkat.
onTextChanged
hanya membutuhkan public void
depan di itu.
Saya telah melakukan sesuatu seperti ini untuk membuatnya tetap sederhana:
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 ]"), "")
}
})
Dengan cara ini kami mengganti semua karakter yang tidak diinginkan di bagian baru dari string sumber dengan string kosong.
The edit_text
variabel adalah EditText
objek kita mengacu kepada.
Kode ditulis dalam bahasa kotlin
.
Dimungkinkan untuk digunakan setOnKeyListener
. Dalam metode ini, kita dapat menyesuaikan input edittext
!
Inilah cara saya membuat filter untuk bidang Nama di Edit Teks. (Huruf pertama adalah CAPS, dan hanya mengizinkan satu spasi setelah setiap kata.
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)});
}
Saya memiliki jawaban yang sama di 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
}
}
}
dan dapatkan kelas dengan fungsi Extension:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}