What I had to do was to implement a text input able to color letters green or red. My piece of code can do this but there is a problem. I can't write an national letter because the popup does not appear.
edit_text.addTextChangedListener(new TextWatcher() {
boolean input_changed = false;
private boolean isInputBlocked()
{
this.input_changed = !this.input_changed;
return !this.input_changed;
}
#Override
public void afterTextChanged(Editable s)
{
// Prevent recursive
if (isInputBlocked()) return;
// Some staff
Outer.this.edit_text.setText(Html.fromHtml(html_input.toString()));
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {}
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count)
{}
});
When I commented Outer.this.edit_text.setText(Html.fromHtml(html_input.toString()));, the popup appears.
The InputFilter helped me resolve the problem:
InputFilter filter = new InputFilter() {
final String good_letter = "<font color='#2FEE0D'>$</font>";
final String bad_letter = "<font color='#FF0000'>$</font>";
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend)
{
String input = dest.toString().substring(0, dstart) + source.
subSequence(start, end) + dest.toString().substring(dend);
StringBuffer output = new StringBuffer();
List<Entry<Character, Boolean>> correction = Learn.this.
learn_manager.getLetters(input);
Log.d(TAG, "afterTextChanged: input size (" + input.length() +
")");
System.out.println(input);
for (int i = dstart; i < dstart + end; i++)
{
if (correction.get(i).getValue())
{
output.append(this.good_letter.replace('$', correction.
get(i).getKey()));
} else {
output.append(this.bad_letter.replace('$', correction.
get(i).getKey()));
}
}
return Html.fromHtml(output.toString());
}
};
Related
I copied code from stackoverflow using InputFilter to force the edit text to have 3 digits before the "." and 2 digits after (2 decimal places). However, I want the system to display 15.00 if user only enters 15?
So scenario I want is.. edit text must have 2 decimal places maximum.. e.g. 12.56 but if user only enters 15 then edit text field adds 2 zeros in the end so 15 -> 15.00
How do i do this in the addTextChangedListener?
Code from stackoverflow regarding inputfilter
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
public DecimalDigitsInputFilter(int digitsBeforeZero,int digitsAfterZero) {
mPattern=Pattern.compile("[0-9]{0," + (digitsBeforeZero-1) + "}+((\\.[0-9]{0," + (digitsAfterZero-1) + "})?)||(\\.)?");
}
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String s = Html.toHtml(dest).replaceAll("\\<.*?>","").replaceAll("\n","");
Matcher matcher = mPattern.matcher(dest);
if (!matcher.matches())
return "";
try {
if(Double.parseDouble(s)<9999.99 && s.contains(".")) {
return null;
}else if ((Double.parseDouble(s)<1000 && !s.contains("."))||source.equals(".")) {
return null;
}else {
return "";
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
/// in main activity
numberReceivedEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(3, 2)});
numberReceivedEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
Please try this
numberReceivedEditText.setFilters(new InputFilter[]{new DecimalDigitsInputFilter(numberReceivedEditText)});
numberReceivedEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (i2 == 0) return;
int cursorLocation = numberReceivedEditText.getSelectionStart();
String data = numberReceivedEditText.getText().toString();
if (!data.isEmpty()) {
if (!data.contains(".")) {
data = data + ".";
}
try {
data = String.format(Locale.JAPANESE, "%.2f", Double.parseDouble(data));
numberReceivedEditText.removeTextChangedListener(this);
numberReceivedEditText.setText(data);
numberReceivedEditText.setSelection(cursorLocation < data.length() ? cursorLocation : cursorLocation - 1, cursorLocation);
numberReceivedEditText.addTextChangedListener(this);
}catch (Exception e){
e.printStackTrace();
}
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
class DecimalDigitsInputFilter implements InputFilter {
TextView tvNumber;
public DecimalDigitsInputFilter(TextView tvNumber) {
this.tvNumber = tvNumber;
}
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
try {
if (Double.parseDouble(tvNumber.getText().toString()) > 1000) {
String[] splitValue = tvNumber.getText().toString().split("\\.");
return splitValue[0].substring(0,3) + "." + splitValue[1];
}
} catch (Exception e) {
return source;
}
return null;
}
}
I want the user to type only letters in the first 5 characters and the next characters would only be numbers.
I've read the answer from this link: Validation allow only number and characters in edit text in android
However when I tried to do what I wanted to do, I'm getting error saying this:
java.lang.StringIndexOutOfBoundsException: length=1; index=1
at java.lang.String.charAt(Native Method)
The codes I've tried to do what I want.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start,
int end, Spanned dest, int dstart, int dend) {
for (int i = start;i < etLettersAndNumbers.getText().length();i++) {
if (etLettersAndNumbers.getText().length() < 4) {
if (!Character.isLetter(source.charAt(i))) {
return "";
}
}
if (etLettersAndNumbers.getText().length() >= 4) {
if (!Character.isDigit(source.charAt(i))) {
return "";
}
}
}
return null;
}
};
etLettersAndNumbers.setFilters(new InputFilter[] {filter});
I'm using dynamic EditText.
try this:
public void set(final EditText etLettersAndNumbers) {
etLettersAndNumbers.addTextChangedListener(new TextWatcher() {
int len = 0;
#Override
public void afterTextChanged(Editable s) {
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String str = etLettersAndNumbers.getText().toString();
char[] st = str.toCharArray();
try {
if (Character.isLetter(st[st.length - 1]) && st.length - 1 < 5) {
System.out.print("Nothing");
} else if (!Character.isLetter(st[st.length - 1]) && st.length - 1 < 5) {
if(count>0)
etLettersAndNumbers.setText("");
} else if (Character.isLetter(st[st.length - 1]) && st.length - 1 >= 5) {
if(count>0)
etLettersAndNumbers.setText("");
}
} catch (Exception e) {
e.getMessage();
}
}
});
}
In my application I want use EditText and I want start characters just English alphabet.
My mean is, First of characters has just English alphabet (a to z).
I write below codes :
registerUsernameEdtTxt.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().length() < 2) {
registerUsernameEdtTxt.setFilters(new InputFilter[]{new InputFilter() {
public CharSequence filter(CharSequence src, int start,
int end, Spanned dst, int dstart, int dend) {
if (src.toString().matches("[a-zA-Z ]+")) {
registerUsernameInptLay.setErrorEnabled(false);
return src;
}
registerUsernameInptLay.setError(context.getResources().getString(R.string.insertJustEnglish));
return "";
}
}});
}
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
}
});
But not work me! How can I it?
Please help me
Try this:
EditText et = findViewById(R.id.text_field);
// This part is to keep the existing filters of the EditText.
InputFilter[] filters = et.getFilters();
InputFilter[] newFilters = Arrays.copyOf(filters, filters.length + 1);
InputFilter firstFilter = new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && source.length() > 0 && dstart == 0){
if (!source.toString().matches("^[A-Za-z].*"))
return "";
}
return null;
}
};
// Add the filter to the array of filters
newFilters[newFilters.length - 1] = firstFilter;
et.setFilters(newFilters);
Can be simplified like this (if the previous InputFilter are not required)
EditText et = findViewById(R.id.text_field);
InputFilter firstFilter = new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && source.length() > 0 && dstart == 0){
if (!source.toString().matches("^[A-Za-z].*"))
return "";
}
return null;
}
};
et.setFilters(new InputFilter[]{firstFilter});
EDIT
If you want to keep the rest of the string (for example if the user pastes the text):
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (source != null && source.length() > 0 && dstart == 0) {
String s = source.toString();
if (!s.matches("^[A-Za-z].*")) {
Toast.makeText(getApplicationContext(), "This is a Toast", Toast.LENGTH_SHORT).show();
return s.substring(1, s.length());
}
}
return null;
}
EDIT 2
The above versions don't work on deletion or when a text is pasted with more than a forbidden char at the beginning (e.g. '88sdfs') as only the first one was removed and the rest kept.
This new version should cover all these cases.
I'd suggest to create a separated class for the InputFilter.
InputFilter firstFilter = new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
if (dstart != 0) { // The modified part is not beginning of the text
return null; // Nothing need to be changed
}
if (source.length() > 0) { // text is added
return onTextAdded(source.toString());
} else { // text is removed
return onTextRemoved(dest, dend);
}
}
private CharSequence onTextRemoved(Spanned dest, int dend) {
// check what the string will look like after the text being removed
String substring = dest.toString().substring(dend, dest.length());
// if there is still a string and it's not valid
if (substring.length() > 0 && !isValid(substring)) {
displayError();
// return the deleted part for the string to not change
return dest.subSequence(0, dend);
}
return null;
}
private String onTextAdded(String s) {
if (isValid(s)) {
return null;
} else {
String substring;
// We want to keep a part of the added string (it can be a paste).
// so we remove all the first characters as long as the string doesn't match
// the requirements
for (int i = 1; i < s.length(); i++) {
substring = s.substring(i, s.length());
if (isValid(substring))
break;
}
displayError();
return substring;
}
}
private boolean isValid(String s) {
return s.matches("^[A-Za-z].*");
}
private void displayError() {
Toast.makeText(getApplicationContext(), "This is a Toast", Toast.LENGTH_SHORT).show();
}
};
et.setFilters(new InputFilter[]{firstFilter});
Add this class to your project:
public class EnglishInputFilter implements InputFilter {
#Override
public CharSequence filter(CharSequence charSequence, int start, int end, Spanned spanned, int dstart, int dend) {
StringBuilder newChars = new StringBuilder(charSequence.toString().substring(start, end));
for (int i = 0; i < newChars.length(); ) {
if (!Character.isLetter(newChars.charAt(i)))
newChars.deleteCharAt(i);
else
i++;
}
return newChars.toString();
}
}
Then do this with your EditText:
myEditText.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS)
myEditText.setFilters(new InputFilter[]{new EnglishInputFilter()});
It also removes no letter characters from pasted strings, if you paste "1A2B" it will really paste "AB"
You can add more filters, for example for limit the total length.
If you want that your edit text should accept starting first character with any English alphabet Then you can use regular expression like;
String regexp = "^([a-zA-Z]+).*$";
Pattern pattern = Pattern.compile(regexp);
boolean ismatches = pattern.matcher("your input that start with the alphabet").matches();
if(ismatches)
do your stuff
else
show error
Hey guys I'm developing an application for Market Transactions and stuff, and the client wants to have a condition on the edit text of type number decimal.
He wants the user to enter only number 5 after the dot if the number is a decimal and only one digit after the dot.
i.e.
15
14
1949
12.33 (not accepted)
12.5 (accepted)
so how to do so please give me some hints
try this and check whether it works.
final String regex = "^\\-?(\\d{0,5}|\\d{0,5}\\.[5]{0,1})$";
((EditText)rootView.findViewById(R.id.editText1)).setFilters(new InputFilter[] {
new InputFilter() {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned destination, int destinationStart, int destinationEnd) {
if (end > start) {
// adding: filter
// build the resulting text
String destinationString = destination.toString();
String resultingTxt = destinationString.substring(0, destinationStart) + source.subSequence(start, end) + destinationString.substring(destinationEnd);
// return null to accept the input or empty to reject it
return resultingTxt.matches(regex) ? null : "";
}
// removing: always accept
return null;
}
}
});
Here user input is checked to match the regular expression and return the input string if it matches and null if not.
<Edittext
android:id="#+id/testing"
android:inputType="numberDecimal"
android:digits="0123456789."
>
</Edittext>
Then, use InputFilter
testing.setFilters(new InputFilter[]{NumberFilter(), new InputFilter.LengthFilter(6)});
//OR
testing.setFilters(new InputFilter[]{NumberFilter()});
Create class for NumberFilter implemenets InputFilter
public class NumberFilter implements InputFilter{
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
// ignore empty space and not number
if (!isNullorEmpty(source.toString()) && !isOnlyNumber(source.toString()))
return "";
//ignore first .
if (!source.toString().charAt(0).equals("."))
return "";
if ((source.toString().charAt(0) != '8' || source.toString().charAt(0) != '9'))
return "";
return null;
}
}
// to allow 1 and 1.2
public static boolean isOnlyNumber(String number) {
return number.matches("(?<=^| )\d+(\.\d+)?(?=$| )");
}
//check empty space or Null
public static boolean isNullorEmpty(String string){
return StringUtils.isEmpty(string);
}
Try this addTextChangedListener.
You need to append 5 to the editText whenever user inputs a dot.
`flag =0;
_field.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if (s.toString().contains(".") && (flag == 0)) {
flag = 1;
_field.setText(_field.getText() + "5");
} else if (s.toString().contains(".") && (flag == 1)) {
} else {
flag = 0;
}
}
});`
How to delete two character at once with the filter?
I am trying to apply a simple filter to an EditText.
It must work as follows:
(want to receive format: 1234 5678....)
===> EDITED: First part works well.
1) when there are 4 digits in EditText and I am entering the 5-th digit -
first must appear a space and then this digit.
2) And I need a reverse for this (during characters deletion) -
the space must be deleted with the 5-th digit.
What is wrong with my code?
editText.setFilters(new InputFilter[]{new DigitsKeyListener(Boolean.FALSE, Boolean.TRUE) {
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
// any chars except backspace
if (!source.equals("")) {
if (dest.length() == 4) {
// here I must add a space and then the source
// ===> EDITED:
return " " + source;
// return super.filter(" " + source, start, end + 1, dest, dstart, dend + 1);
} // backspace entered
} else {
if (dest.length() == 6) {
// here I must delete the 6-th character
// and the space before
return super.filter(source, 0, 0, dest, 5, 6);
}
}
return null;
}
}});
Please use this
public class CustomFormatWatcher implements TextWatcher {
private int size;
public CustomFormatWatcher(int size) {
this.size = size;
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable) {
char hyphen = ' ';
char c = 0;
if (editable.length() > 0) {
c = editable.charAt(editable.length() - 1);
if (c == hyphen) {
editable.delete(editable.length() - 1, editable.length());
}
}
if (editable.length() > 0 && (editable.length() % size) == 0) {
c = editable.charAt(editable.length() - 1);
if (hyphen == c) {
editable.delete(editable.length() - 1, editable.length());
}
}
if (editable.length() > 0 && (editable.length() % size) == 0) {
c = editable.charAt(editable.length() - 1);
// Only if its a digit where there should be a space we insert a hyphen
if (Character.isDigit(c) && TextUtils.split(editable.toString(), String.valueOf(hyphen)).length <= 3) {
editable.insert(editable.length() - 1, String.valueOf(hyphen));
}
}
}
}
and then use
myEditText.addTextChangedListener(new CustomFormatWatcher());
I suggest you to use TextWatcher to format your EditText input, because InputFilter is generally used for input restrictions, to decides what can be typed not to format the text.
You'll get your desired output with this code:
String mTextValue;
Character mLastChar = '\0'; // init with empty character
int mKeyDel;
myEditText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
String eachBlock[] = myEditText.getText().toString().split(" ");
myEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL)
mKeyDel = 1;
return false;
}
});
if (mKeyDel == 0) {
if (((myEditText.getText().length() + 1) % 5) == 0) {
myEditText.setText(myEditText.getText() + " ");
myEditText.setSelection(myEditText.getText().length());
}
mTextValue = myEditText.getText().toString();
} else {
mTextValue = myEditText.getText().toString();
if (mLastChar.equals(' ')) {
mTextValue = mTextValue.substring(0, mTextValue.length() - 1);
myEditText.setText(mTextValue);
myEditText.setSelection(mTextValue.length());
}
mKeyDel = 0;
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if (s.length()>0) {// save the last char value
mLastChar = s.charAt(s.length() - 1);
} else {
mLastChar = '\0';
}
}
#Override
public void afterTextChanged(Editable s) {}
});