ฉันต้องการ จำกัด ตัวอักษรไว้ที่ 0-9, az, AZ และ spacebar เท่านั้น การตั้งค่าประเภทอินพุตฉันสามารถ จำกัด ตัวเลขได้ แต่ฉันไม่สามารถหาวิธีของ Inputfilter ในการดูเอกสาร
ฉันต้องการ จำกัด ตัวอักษรไว้ที่ 0-9, az, AZ และ spacebar เท่านั้น การตั้งค่าประเภทอินพุตฉันสามารถ จำกัด ตัวเลขได้ แต่ฉันไม่สามารถหาวิธีของ Inputfilter ในการดูเอกสาร
คำตอบ:
ฉันพบสิ่งนี้ในฟอรัมอื่น ทำงานเหมือนแชมป์
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
มีความซับซ้อนเล็กน้อยในรุ่น Android ที่แสดงคำแนะนำพจนานุกรม บางครั้งคุณได้รับ a SpannableStringBuilder
ซึ่งบางครั้งก็ธรรมดาString
ในsource
พารามิเตอร์
ต่อไปนี้InputFilter
ควรทำงาน อย่าลังเลที่จะปรับปรุงรหัสนี้!
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
เข้าABให้ฉันAABเหมือนเมื่อลองคำตอบก่อนหน้า โชคดีที่ฉันสามารถแก้ไขได้โดยใช้ @florian solution ด้านล่าง
ง่ายกว่ามาก:
<EditText
android:inputType="text"
android:digits="0,1,2,3,4,5,6,7,8,9,*,qwertzuiopasdfghjklyxcvbnm" />
","
ในระหว่าง คุณสามารถใช้สิ่งนี้"0123456789qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"
imeOptions="actionNext"
ฯลฯ
คำตอบที่โพสต์ไม่ได้ผลสำหรับฉัน ฉันมาพร้อมทางออกของตัวเอง:
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
สามารถมีตัวกรองของตัวเองได้แล้วเช่นตัวกรองความยาว ดังนั้นแทนที่จะแค่ลบล้างตัวกรองคุณน่าจะต้องการเพิ่มตัวกรองของคุณไปยังตัวกรองที่มีอยู่แล้ว
ใช้สิ่งนี้ทำงานได้ 100% ความต้องการของคุณและง่ายมาก
<EditText
android:inputType="textFilter"
android:digits="@string/myAlphaNumeric" />
ใน strings.xml
<string name="myAlphaNumeric">abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789</string>
เพื่อหลีกเลี่ยงอักขระพิเศษในประเภทอินพุต
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;
}
};
คุณสามารถตั้งค่าตัวกรองเป็นข้อความแก้ไขของคุณด้านล่าง
edtText.setFilters(new InputFilter[] { filter });
นอกจากคำตอบที่ยอมรับแล้วยังสามารถใช้เช่น: android:inputType="textCapCharacters"
เป็นคุณสมบัติ<EditText>
เพื่อรับเฉพาะอักษรตัวพิมพ์ใหญ่ (และตัวเลข)
ด้วยเหตุผลบางอย่างตัวสร้างคลาส android.text.LoginFilter มีการกำหนดขอบเขตแพ็กเกจดังนั้นคุณจึงไม่สามารถขยายได้โดยตรง (แม้ว่าจะเหมือนกับโค้ดนี้) แต่คุณสามารถขยาย LoginFilter.UsernameFilterGeneric! แล้วคุณมีสิ่งนี้:
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;
}
}
นี้ไม่ได้มีการบันทึกไว้จริงๆ แต่มันก็เป็นส่วนหนึ่งของ lib หลักและแหล่งที่มาตรงไปตรงมา ฉันใช้มันมาระยะหนึ่งแล้วจนถึงตอนนี้ก็ไม่มีปัญหาแม้ว่าฉันจะยอมรับว่าฉันไม่ได้ลองทำอะไรที่ซับซ้อนเกี่ยวกับ spannables
มันถูกต้องวิธีที่ดีที่สุดในการแก้ไขมันใน XML Layout เองโดยใช้:
<EditText
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
Florian Fröhlichเป็นผู้ชี้ให้เห็นอย่างถูกต้องมันทำงานได้ดีสำหรับการดูข้อความ
<TextView
android:inputType="text"
android:digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" />
เพียงแค่คำเตือนตัวละครที่กล่าวถึงในandroid:digits
จะปรากฏขึ้นเท่านั้นดังนั้นโปรดระวังอย่าพลาดชุดอักขระใด ๆ :)
inputType
ไม่มีผลต่อการกรอง
วิธีแก้ปัญหาอย่างง่ายนี้ทำงานสำหรับฉันเมื่อฉันต้องการป้องกันไม่ให้ผู้ใช้ป้อนสตริงว่างใน EditText แน่นอนคุณสามารถเพิ่มตัวอักษรเพิ่มเติมได้:
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});
}
หากคุณ subclass InputFilter คุณสามารถสร้าง InputFilter ของคุณเองที่จะกรองอักขระที่ไม่ใช่ตัวอักษรและตัวเลข
อินเทอร์เฟซ InputFilter มีหนึ่งวิธี filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
และให้ข้อมูลทั้งหมดที่คุณต้องรู้เกี่ยวกับตัวละครที่ถูกป้อนลงใน EditText ที่ได้รับมอบหมาย
เมื่อคุณสร้าง InputFilter ของคุณเองแล้วคุณสามารถกำหนดให้กับ EditText ได้โดยเรียก setFilters (... )
http://developer.android.com/reference/android/text/InputFilter.html#filter(java.lang.CharSequence , int, int, android.text.Spanned, int, int)
ไม่สนใจสิ่งที่บุคคลอื่นจัดการเพื่อจัดการคำแนะนำพจนานุกรมอย่างถูกต้องฉันพบว่ารหัสต่อไปนี้ใช้ได้ผล
แหล่งที่มาเติบโตตามคำแนะนำที่เพิ่มขึ้นดังนั้นเราต้องดูว่ามีตัวละครกี่ตัวที่คาดหวังให้เราแทนที่ก่อนที่เราจะคืนสิ่งใด
หากเราไม่มีอักขระที่ไม่ถูกต้องให้ส่งคืน null เพื่อให้การแทนที่เริ่มต้นเกิดขึ้น
มิฉะนั้นเราจะต้องแยกอักขระที่ถูกต้องออกจากสตริงย่อยที่จริงจะถูกวางลงใน 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;
}
};
เพื่อป้องกันคำใน edittext สร้างคลาสที่คุณสามารถใช้ได้ทุกเวลา
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;
}
}
เพิ่มเป็นstrings.xml
:
<string name="vin_code_mask">0123456789abcdefghjklmnprstuvwxyz</string>
XML :
android:digits="@string/vin_code_mask"
รหัสใน 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
}
แปลก แต่ก็ใช้งานได้ดีกับคีย์บอร์ดนุ่มของอีมูเลเตอร์
คำเตือน! รหัสต่อไปนี้จะกรองตัวอักษรและสัญลักษณ์อื่น ๆ ทั้งหมดยกเว้นตัวเลขสำหรับแป้นพิมพ์ซอฟต์แวร์ เฉพาะแป้นพิมพ์ดิจิทัลเท่านั้นที่จะปรากฏบนสมาร์ทโฟน
edit_text.keyListener = DigitsKeyListener.getInstance(context.getString(R.string.vin_code_mask))
ฉันก็มักจะตั้งmaxLength
, ,filters
inputType
นี่เป็นเธรดเก่า แต่โซลูชันที่มีวัตถุประสงค์ทั้งหมดมีปัญหา (ขึ้นอยู่กับอุปกรณ์ / รุ่น Android / คีย์บอร์ด)
แนวทางที่แตกต่าง
ดังนั้นในที่สุดฉันก็ไปด้วยวิธีที่แตกต่างแทนที่จะใช้การInputFilter
ใช้งานที่มีปัญหาฉันกำลังใช้TextWatcher
และTextChangedListener
ของEditText
ของ
รหัสเต็ม (ตัวอย่าง)
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
}
});
เหตุผลInputFilter
ไม่ได้เป็นทางออกที่ดีใน Android เพราะมันขึ้นอยู่กับการใช้แป้นพิมพ์ EditText
อินพุตแป้นพิมพ์จะถูกกรองก่อนที่จะป้อนข้อมูลที่ถูกส่งไปยัง แต่เนื่องจากคีย์บอร์ดบางตัวมีการใช้งานที่แตกต่างกันสำหรับการInputFilter.filter()
เรียกใช้นี่เป็นปัญหา
ในทางกลับกันTextWatcher
ไม่สนใจเกี่ยวกับการใช้งานคีย์บอร์ดมันช่วยให้เราสร้างโซลูชันที่ง่ายและให้แน่ใจว่ามันจะทำงานบนอุปกรณ์ทั้งหมด
onTextChanged
เพียงแค่ความต้องการpublic void
ในด้านหน้าของมัน
ฉันทำสิ่งนี้เพื่อให้ง่าย:
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 ]"), "")
}
})
ด้วยวิธีนี้เราจะแทนที่ตัวละครที่ไม่ต้องการทั้งหมดในส่วนใหม่ของสตริงต้นฉบับด้วยสตริงว่าง
edit_text
ตัวแปรเป็นEditText
วัตถุที่เราหมายถึง
kotlin
รหัสถูกเขียนใน
setOnKeyListener
มันเป็นไปได้ที่จะใช้ ในวิธีนี้เราสามารถปรับแต่งอินพุตedittext
!
นี่คือวิธีที่ฉันสร้างตัวกรองสำหรับฟิลด์ชื่อในแก้ไขข้อความ (ตัวอักษรตัวแรกคือ CAPS และอนุญาตให้เว้นวรรคเดียวหลังจากทุกคำ
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:
/**
* 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
}
}
}
และรับคลาสด้วยฟังก์ชัน Extension:
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}