Câu trả lời:
Tôi tìm thấy điều này trên một diễn đàn khác. Hoạt động như một nhà vô địch.
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 là một chút phức tạp trong các phiên bản Android hiển thị các đề xuất từ điển. Đôi khi bạn nhận được một SpannableStringBuilder
, đôi khi một đồng bằng String
trong source
tham số.
Sau đây InputFilter
nên làm việc. Hãy cải thiện mã này!
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
vào AB cho tôi AAB như khi thử câu trả lời trước. May mắn thay, tôi đã có thể làm việc xung quanh nó bằng cách sử dụng giải pháp @florian bên dưới.
dễ dàng hơn nhiều:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
giữa. Bạn có thể sử dụng một cái gì đó như thế này"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
, v.v.
Không có câu trả lời được đăng đã làm việc cho tôi. Tôi đến với giải pháp của riêng tôi:
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
có thể đã có bộ lọc riêng, ví dụ: bộ lọc độ dài. Vì vậy, thay vì chỉ ghi đè các bộ lọc, rất có thể bạn muốn thêm các bộ lọc của mình vào các bộ lọc đã có.
Sử dụng công việc này 100% nhu cầu của bạn và rất đơn giản.
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
Trong chuỗi DOM
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
Để tránh các ký tự đặc biệt trong kiểu đầu vào
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;
}
};
Bạn có thể đặt bộ lọc cho văn bản chỉnh sửa của mình như bên dưới
edtText.setFilters(new InputFilter[] { filter });
Ngoài câu trả lời được chấp nhận, cũng có thể sử dụng, ví dụ: android:inputType="textCapCharacters"
như một thuộc tính <EditText>
để chỉ chấp nhận các ký tự chữ hoa (và số).
Vì một số lý do, hàm tạo của lớp android.text.LoginFilter nằm trong phạm vi gói, vì vậy bạn không thể trực tiếp mở rộng nó (mặc dù nó sẽ giống hệt với mã này). Nhưng bạn có thể mở rộng LoginFilter.UsernameFilterGeneric! Sau đó, bạn chỉ cần có điều này:
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;
}
}
Đây không phải là tài liệu thực sự, nhưng nó là một phần của lib cốt lõi, và nguồn rất đơn giản . Tôi đã sử dụng nó được một thời gian rồi, cho đến nay không có vấn đề gì, mặc dù tôi thừa nhận tôi đã không thử làm bất cứ điều gì phức tạp liên quan đến spannables.
Đúng vậy, cách tốt nhất để khắc phục nó trong chính Bố cục XML bằng cách sử dụng:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
như được chỉ ra bởi Florian Fröhlich, nó hoạt động tốt cho các chế độ xem văn bản.
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Chỉ cần một lời cảnh báo, các ký tự được đề cập trong android:digits
sẽ chỉ được hiển thị, vì vậy hãy cẩn thận để không bỏ lỡ bất kỳ bộ ký tự nào :)
inputType
không ảnh hưởng đến việc lọc.
Giải pháp đơn giản này hiệu quả với tôi khi tôi cần ngăn người dùng nhập các chuỗi trống vào EditText. Tất nhiên bạn có thể thêm nhiều ký tự:
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});
}
Nếu bạn phân lớp InputFilter, bạn có thể tạo InputFilter của riêng mình để lọc bất kỳ ký tự không phải là số alpha.
Giao diện InputFilter có một phương thức filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
và nó cung cấp cho bạn tất cả thông tin bạn cần biết về các ký tự được nhập vào EditText mà nó được gán.
Khi bạn đã tạo InputFilter của riêng mình, bạn có thể gán nó cho EditText bằng cách gọi setFilters (...).
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text.Spned, int, int)
Bỏ qua các công cụ span mà người khác đã xử lý, để xử lý đúng các đề xuất từ điển, tôi thấy đoạn mã sau hoạt động.
Nguồn phát triển khi đề xuất tăng lên, vì vậy chúng tôi phải xem có bao nhiêu nhân vật thực sự mong đợi chúng tôi thay thế trước khi chúng tôi trả lại bất cứ điều gì.
Nếu chúng tôi không có bất kỳ ký tự không hợp lệ nào, hãy trả về null để thay thế mặc định xảy ra.
Mặt khác, chúng ta cần trích xuất các ký tự hợp lệ từ chuỗi con THỰC SỰ sẽ được đặt vào 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;
}
};
để ngăn chặn các từ trong edittext. tạo một lớp mà bạn có thể sử dụng bất cứ lúc nào
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;
}
}
Đầu tiên thêm vào strings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
Mã trong 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
}
Lạ, nhưng nó hoạt động kỳ lạ trên bàn phím mềm của trình giả lập.
Cảnh báo! Đoạn mã sau sẽ lọc tất cả các chữ cái và các ký hiệu khác trừ các chữ số cho bàn phím phần mềm. Chỉ bàn phím kỹ thuật số sẽ xuất hiện trên điện thoại thông minh.
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
Tôi cũng thường được thiết lập maxLength
, filters
, inputType
.
Đây là một chủ đề cũ, nhưng tất cả các giải pháp có mục đích đều có vấn đề (tùy thuộc vào thiết bị / phiên bản Android / Bàn phím).
PHƯƠNG PHÁP KHÁC NHAU
Vì vậy, cuối cùng tôi đã đi với một cách tiếp cận khác, thay vì sử dụng InputFilter
triển khai có vấn đề, tôi đang sử dụng TextWatcher
và TextChangedListener
của EditText
.
MÃ ĐẦY ĐỦ (VÍ DỤ)
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
}
});
Lý do InputFilter
không phải là một giải pháp tốt trong Android là vì nó phụ thuộc vào việc thực hiện bàn phím. Đầu vào Bàn phím đang được lọc trước khi đầu vào được chuyển đến EditText
. Nhưng, bởi vì một số bàn phím có các triển khai khác nhau cho việc InputFilter.filter()
gọi, nên đây là vấn đề.
Mặt khác, TextWatcher
không quan tâm đến việc thực hiện bàn phím, nó cho phép chúng tôi tạo ra một giải pháp đơn giản và chắc chắn rằng nó sẽ hoạt động trên tất cả các thiết bị.
onTextChanged
giản chỉ cần một public void
ở phía trước của nó.
Tôi đã làm một cái gì đó như thế này để giữ cho nó đơn giản:
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 ]"), "")
}
})
Bằng cách này, chúng tôi sẽ thay thế tất cả các ký tự không mong muốn trong phần mới của chuỗi nguồn bằng một chuỗi trống.
Các edit_text
biến làEditText
đối tượng chúng ta đang đề cập đến.
Mã được viết bằng kotlin
.
Có thể sử dụng setOnKeyListener
. Trong phương pháp này, chúng ta có thể tùy chỉnh đầu vào edittext
!
Đây là cách tôi tạo bộ lọc cho trường Tên trong Chỉnh sửa văn bản. (Chữ cái đầu tiên là CAPS và chỉ cho phép một khoảng trống sau mỗi từ.
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)});
}
Tôi có câu trả lời tương tự trong 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
}
}
}
và nhận lớp với chức năng Mở rộng:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}