답변:
나는 다른 포럼에서 이것을 발견했다. 챔피언처럼 작동합니다.
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 버전에서는 약간 복잡합니다. 때로는 매개 변수 에 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
입력 하면 이전 답변을 시도 할 때와 같은 AAB 가 표시됩니다. 다행히 아래의 @florian 솔루션을 사용하여 해결할 수있었습니다.
훨씬 쉽게:
<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
이미 길이 필터와 같은 자체 필터를 가질 수 있습니다. 따라서 필터를 재정의하는 대신 기존 필터에 필터를 추가하려고합니다.
입력 유형에서 특수 문자를 피하려면
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.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의 일부이며 소스는 간단 합니다. 나는 지금까지 그것을 사용해 왔지만 지금까지 아무런 문제가 없었지만 스패너 블과 관련된 복잡한 작업은 시도하지 않았다는 것을 인정합니다.
XML 레이아웃 자체에서 다음을 사용하여 수정하는 가장 좋은 방법은 다음과 같습니다.
<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});
}
InputFilter를 서브 클래 싱하는 경우 영숫자가 아닌 문자를 필터링하는 고유 한 InputFilter를 작성할 수 있습니다.
InputFilter Interface에는 한 가지 메소드가 있으며 filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend)
, EditText에 입력 된 문자에 대해 알아야하는 모든 정보를 제공합니다.
고유 한 InputFilter를 작성하면 setFilters (...)를 호출하여 EditText에 지정할 수 있습니다.
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;
}
};
편집 텍스트에서 단어를 방지합니다. 언제든 사용할 수있는 클래스를 만듭니다.
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"
코 틀린 코드 :
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
는 키보드 구현에 달려 있기 때문에 안드로이드에서 좋은 해결책이 아닙니다. 입력이로 전달되기 전에 키보드 입력이 필터링 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
.
이것은 텍스트 편집에서 이름 필드에 대한 필터를 생성 한 방법입니다. 첫 번째 문자는 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
}
}
}
확장 기능을 사용하여 클래스를 가져옵니다.
fun EditText.filterByDataType(filterType: Int) {
this.filters = arrayOf<InputFilter>(InputFilterAlphanumeric(filterType))
}