I have an EditText where the user wants to enter the price. In order to maintain uniformity, I decided to automatically include the decimal values.
Hence "1" entered by user would become "1.00" for example.
Now, after working with my inefficient code, I can across a better code in StackOverFlow
amountEditText.setRawInputType(Configuration.KEYBOARD_12KEY);
amountEditText.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().matches("^\\$(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
{
String userInput= ""+s.toString().replaceAll("[^\\d]", "");
StringBuilder cashAmountBuilder = new StringBuilder(userInput);
while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0') {
cashAmountBuilder.deleteCharAt(0);
}
while (cashAmountBuilder.length() < 3) {
cashAmountBuilder.insert(0, '0');
}
cashAmountBuilder.insert(cashAmountBuilder.length()-2, '.');
cashAmountBuilder.insert(0, '$');
amountEditText.setText(cashAmountBuilder.toString());
// keeps the cursor always to the right
Selection.setSelection(amountEditText.getText(), cashAmountBuilder.toString().length());
}
}
});
With the above code, the decimal value starts getting included once the user starts entering the number. But, the numerical value added by the user will be displayed with $ symbol. Hence, I made a little modification to the code in Line 07 and deleted Line 19.
The new code is
returnPrice.setRawInputType(Configuration.KEYBOARD_12KEY);
returnPrice.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().matches("^(\\d{1,3}(\\,\\d{3})*|(\\d+))(\\.\\d{2})?$"))
{
String userInput= ""+s.toString().replaceAll("[^\\d]", "");
StringBuilder cashAmountBuilder = new StringBuilder(userInput);
while (cashAmountBuilder.length() > 3 && cashAmountBuilder.charAt(0) == '0') {
cashAmountBuilder.deleteCharAt(0);
}
while (cashAmountBuilder.length() < 3) {
cashAmountBuilder.insert(0, '0');
}
cashAmountBuilder.insert(cashAmountBuilder.length()-2, '.');
returnPrice.setText(cashAmountBuilder.toString());
// keeps the cursor always to the right
Selection.setSelection(returnPrice.getText(), cashAmountBuilder.toString().length());
}
}
});
My Problem
So the problem I am facing in case 02 is, when I am entering the numeric value in EditText - unless I am entering the decimal dot, the numeric value in EditText gets displayed as an integer.
For example : Case 01
For displaying 100.00 as I go on typing, the value starts displaying as $0.01, then $0.10, then $1.00, $10.00 and finally $100.00. At any instance, I don't need to enter a decimal dot manually in this case.
For example : Case 02
For displaying 100.00 as I go on typing, the value starts displaying as 1, then 10, then 100. Now, if I press the decimal dot on soft keyboard, the 100 becomes 1.00 and on typing the value turns 10.00 and finally 100.00. If the decimal dot is not touched on the keyboard, the resulting value on entering 10000 is 10000 and not 100.00.
What's the error I made? Any suggestions?
Related
I have EditText in myApp with this TextWatcher and numberSigned input type:
TextWatcher() {
#Override
public void afterTextChanged(Editable s)
{
codeinput.removeTextChangedListener(this);
String text = s.toString();
text = text.replaceAll("[^0-9]", "");
if (text.length() > 4)
text = text.substring(0, 4);
String newText = "";
for (char c : text.toCharArray())
newText += c + " ";
text = newText.trim();
String substring = "_ _ _ _".substring(text.length());
text += substring;
int length = text.replaceAll("([ ]?[_])+$", "").length();
codeinput.setText(text);
codeinput.setSelection(length);
codeinput.addTextChangedListener(this);
}
#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 change input type from numberSigned to numberPassword - all symbols in my EditText is hidden, i want to hide only numbers. How can i do it?
I'm affraid that password type field hides all characters and you can't do anything with that
but consider using setLetterSpacing and don't use spaces (method available since API21)
if you need lower API support and you still want to use numberPassword then you have to set up 4 EditTexts - use editText.requestFocus for jumping to another/next View. or you may keep one EditText with numberSigned, but exchange during text entering all digits to asterisks (keeping digits in some separated value, as editText.getText will return you only asterisks)
I'm currently doing an EditText where the user can type in one row of text. But I have the issue with setting it's max length. If I set it to a specific number it becomes very unpredictable since spaces takes up more for some reason. So I can type in "asdnknfoisanfo" etc and get the correct length I want, but when you start typing with spaces between the words the length get's smaller and doesn't fill the whole EditText.
<EditText
android:id="#+id/imageDescriptionTextEdit"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:hint="Enter a description of this picture.."
android:textSize="15sp"
android:textColorHint="#E9E9E9"
android:textColor="#ffffff"
android:maxEms="26"
android:imeOptions="actionDone"
android:typeface="monospace"
android:minEms="3"
android:singleLine="true"
fontPath="fonts/VarelaRound-Regular.ttf"
tools:ignore="MissingPrefix"/>
What I would say to be the ultimate solution is to set the length of characters to the length of the EditText itself. Then for sure, the user have the correct capacity always. Is this possible? Or are there another solution to my problem?
You can try with this.
String mStringStr = mEditText1.getText().toString().replaceAll("\\s", "");
Now you can get the actual length in string mStringStr(Without blank space)
mStringStr.length();
I hope this may help you.. :)
Try with this conditional
if(findViewById(R.id.imageDescriptionTextEdit).getText().toString().trim().length() <= "your max length here"){
//Do something
} else {
//Show alert message
}
What you can do is to remove the spaces from the input using below code
String input = Your_EditText.getText().toString();
input = input.replace(" ", "");
Then you can get the length of the string using
int inputlength = input.length();
Then you can check if the input is okay or not
so , overall the code should be
private final TextWatcher mywatcher = new TextWatcher() {
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
String input = Your_EditText.getText().toString();
input = input.replace(" ", "");
int inputlength = input.length();
if(inputlength>your_defined_length)
{
//do what you want to do
}
}
public void afterTextChanged(Editable s) {
}
};
Dont forget to add this watcher to your editText
Your_EditText.addTextChangedListener(mywatcher);
You can try it programatically :
final EditText et = (EditText)findViewById(R.id.editText);
et.addTextChangedListener(new TextWatcher() {
int yourMaxLength = 10;
boolean canNotAddMore = false;
String maxText = "";
public void afterTextChanged(Editable s) {
if(canNotAddMore){
et.removeTextChangedListener(this);
et.setText(maxText);
et.addTextChangedListener(this);
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
String realCoontent = s.toString().trim().replace(" ", "");
if(realCoontent.length() >= yourMaxLength){
canNotAddMore = true;
maxText = s.toString();
}
}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
}
This example will remove the spaces from the list of characters counted to determine if the max number of characters is reached.
For example for a limit of 10 characters, the user can enter :
"1234567890"
or
"1 2 3 4 5 6 7 8 9 0"
You can measure the width of the typed input text with a Paint object:
EditText input = findViewById(R.id.imageDescriptionTextEdit) // Your EditText
final Paint paint = input.getPaint();
float textWidth = paint.measureText(input.getText().toString());
if (textWidth > input.getWidth()) {
// Prevent further input.
}
You can combine this check with a TextWatcher.
I have an edit text in my android application and I want to avoid from the user to enter an input when the string length in bytes reaches to the limit.
It works fine in english, but not in hebrew.
The limit is 256, so when the input is in hebrew, I can insert only 128 characters. The problem is while I insert hebrew letters with punctuation.
Lets say that I insert a dot, which is 1 byte, it allows me to enter more than 128 characters , even when the characters are only hebrew letters and punctuation.
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = s.toString().getBytes().length;
if (length == bytes_limit)
{
str = s.toString();
}
else if (length > bytes_limit)
{
input.setText(str);
input.setSelection(str.length());
}
}
Update:
String example: "שלום, מה שלומך"
Update 2:
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
int length = s.toString().getBytes().length;
if (length <= bytes_limit)
{
str = s.toString();
}
else if (length > bytes_limit)
{
input.setText(str);
input.setSelection(str.length());
}
}
Try specifying the charset eg
int length = s.toString().getBytes("UTF-8").length;
replacing UTF-8 with the character set that you need
See
bytes of a string in java?
And
Will String.getBytes("UTF-16") return the same result on all platforms?
Punctuations are characters too, you write them in addition to the hebrew letter you want to write (if i am not wrong, you can add them with ALT + XXXX).
They are character like any others so when you write them, you are adding characters.
A dot(.) doesn't have punctuation so it takes only one byte.
To solve it, you can remove all of the punctuatuion.
You can create a function to ignore all the punctuation:
private String removePunctuation(String s)
{
for(int i = 0; i < s.length(); i++)
{
if(!(s.charAt(i) <= 'ת' && s.charAt(i) >= 'א'))
{
s = s.substring(0,i) + s.substring(i+1);
}
}
return s;
}
note the it will delete all of the punctuation, including - and : and so on...
You can add exceptions to the condition, enabling '-' or others.
Good luck :)
Stuck on this which im sure there is an easy solution to, just cannot work it out!!
I have tried decmialformat, numberformat, string.format() etc and nothing works. .
code below, i want to calculation to just show the output limited to 2 decimal places. Have spent the last 2 hours trying various methods all of which causes the app to crash when run...
Output = (Output1 / (1 -(Output2/100)))
String OutputString = String.valueOf(Output);
Num.setText(OutputString);
Try this :
String OutputString = String.format("%.2f", Output);
Num.setText(OutputString);
String.format() to make sure you only get 2 decimal places in your output.
please try this:
double Output = (Output1 / (1 -(Output2/100d)))
Num.setText(String.format("%.2f",Output));
Hope this solves your problem.
Best regards
If you want to Limit the number of Digits before and after the 'decimal_point' then you can use my solution.
private class DecimalNumberFormatTextWatcher implements TextWatcher{
int pos;
int digitsBeforeDecimal = 6;
int digitsAfterDecimal = 2;
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
if(s.length() > 2)
pos = start;
else {
pos = start + 2;
}
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
mEdittext.removeTextChangedListener(this);
String text = s.toString();
if(text!= null && !text.equals("")){
if(!text.contains("$")){ //if it does not contains $
text = "$"+text;
} else {
if (text.indexOf("$") > 0) { //user entered value before $
text = s.delete(0, text.indexOf("$")).toString();
}else {
if(!text.contains(".")){ // not a fractional value
if(text.length() > digitsBeforeDecimal+1) { //cannot be more than 6 digits
text = s.delete(pos, pos+1).toString();
}
} else { //a fractional value
if(text.indexOf(".") - text.indexOf("$") > digitsBeforeDecimal+1){ //non fractional part cannot be more than 6
text = s.delete(pos,pos+1).toString();
}
if((text.length() - text.indexOf(".")) > digitsAfterDecimal+1) { //fractinal part cannot be more than 2 digits
text = s.delete(text.indexOf(".") + 2, text.length() - 1).toString();
}
}
}
}
}
mEdittext.setText(text);
mEdittext.setSelection(pos);
mEdittext.addTextChangedListener(this);
}
}
mEdittext.addTextChangedListener(new DecimalNumberFormatTextWatcher());
This also adds a currency sign as soon as the user types the value.
HOPE THIS HELPS ANYONE.
On my android app, first time when app runs, user must type a license. The license's format is ###-XXX-###-### where # is a number, X is a character. I put the format as hint but it is not sufficient. How can I make like this and user does not enter -, it just appear after 3 characters ?
UPDATE :
That's my code and it works :
licenseEditText.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
System.out.println("afterTextChanged");
if (s.length() == 3) {
s.append("-");
}
if (s.length() == 7) {
s.append("-");
}
if (s.length() == 11) {
s.append("-");
}
if (s.length() == 15)
ok.performClick();
}
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
System.out.println("beforeTextChanged");
}
public void onTextChanged(CharSequence s, int start, int before,
int count) {
System.out.println("onTextChanges");
}
});
set a TextWatcher , inside it compare intered text with a regularExpression . and put other code like after first 3 charachets append "-" to intered characterSet .
you can use 4 EditTexts and attach textwathers to them - a windows-like license input
Try to use the % operator
if( s.length() == 15) {
// s.length() = 15
} else if( s.length() % 4 == 3) {
// s.length = {3, 7, 11, 19, ....}
// so s.length != 15
}
In this way you have less code duplication. For more information check: Wikipedia - Modulo operation