EditeText On text changed is crashing - java

I have to convert some numeric editText in double and after text changed do a simple math operation. Everything works fine except On Text Changed: it crash whatever I do (also to change TextView with "hello world").
Here's my code:
hEditText.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)
{
Double hDouble = Double.parseDouble(hEditText.toString());
Double bDouble = Double.parseDouble(bEditText.toString());
Double mDouble = Double.parseDouble(mEditText.getText().toString());
Double miDouble = Double.parseDouble(miEditText.getText().toString());
lResult.setText("" + Math.sqrt((hDouble * hDouble) + (bDouble * bDouble)));
}
#Override
public void afterTextChanged(Editable editable) {
}
});
LOG
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.cosmo.fisicapp, PID: 21198
java.lang.NumberFormatException: empty String
at java.lang.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1071)
at java.lang.Double.parseDouble(Double.java:547)
at com.example.cosmo.fisicapp.Equilibrio$1.afterTextChanged(Equilibrio.java:47)
at android.widget.TextView.sendAfterTextChanged(TextView.java:8525)
at android.widget.TextView$ChangeWatcher.afterTextChanged(TextView.java:10788)
at android.text.SpannableStringBuilder.sendAfterTextChanged(SpannableStringBuilder.java:1222)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:583)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:509)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:508)
at android.text.method.NumberKeyListener.onKeyDown(NumberKeyListener.java:121)
at android.widget.TextView.doKeyDown(TextView.java:6533)
at android.widget.TextView.onKeyDown(TextView.java:6323)
at android.view.KeyEvent.dispatch(KeyEvent.java:2742)
at android.view.View.dispatchKeyEvent(View.java:9949)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.widget.ScrollView.dispatchKeyEvent(ScrollView.java:391)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1667)
at com.android.internal.policy.DecorView.superDispatchKeyEvent(DecorView.java:439)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1861)
at android.app.Activity.dispatchKeyEvent(Activity.java:3141)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:535)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:59)
at android.support.v7.app.AppCompatDelegateImpl$AppCompatWindowCallback.dispatchKeyEvent(AppCompatDelegateImpl.java:2530)
at com.android.internal.policy.DecorView.dispatchKeyEvent(DecorView.java:353)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4742)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4713)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4249)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4302)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4268)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4395)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4276)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4452)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4249)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4302)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4268)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4276)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4249)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6676)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6650)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6611)
at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3917)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

hEditText.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(!charSequence.equals("")){
Double hDouble = Double.parseDouble(charSequence.toString());
Double bDouble = Double.parseDouble(charSequence.toString());
Double mDouble = Double.parseDouble(charSequence.getText().toString());
Double miDouble = Double.parseDouble(charSequence.getText().toString());
lResult.setText("" + Math.sqrt((hDouble * hDouble) + (bDouble * bDouble)));
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});

Try moving your code to :
#Override
public void afterTextChanged(Editable editable) {
Double hDouble = Double.parseDouble(hEditText.toString());
Double bDouble = Double.parseDouble(bEditText.toString());
Double mDouble = Double.parseDouble(mEditText.getText().toString());
Double miDouble = Double.parseDouble(miEditText.getText().toString());
lResult.setText("" + Math.sqrt((hDouble * hDouble) + (bDouble * bDouble)));
}

Trying changing the following lines:
Double hDouble = Double.parseDouble(hEditText.toString()); to
Double hDouble = Double.parseDouble(hEditText.getText().trim()); and the other lines

Your app would crash every time the parser doesn't produce a Double. Enclose every transformation from String to Double in a try/catch. If the user types anything other than numbers or ., or clears the EditText
then the app will crash

The method afterTextChanged can't crash because it is empty. The method onTextChanged, on the other hand, which makes extensive use of Double.parseDouble(String) most definitely can, as this will throw a NumberFormatException if you give it something that can't be converted to a double. See the documentation.
To get around this, one possibility is to make a helper method so that you're not putting try-catch blocks everywhere and decide either to catch the exception and return a default value (such as 0D) or let it propagate.
For example:
private double toDouble(String raw) {
double val;
try {
val = Double.parseDouble(raw);
} catch (NumberFormatException e) {
val = 0D;
}
return val;
}
then your code in onTextChanged becomes
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
Double hDouble = toDouble(hEditText.toString());
Double bDouble = toDouble(bEditText.toString());
Double mDouble = toDouble(mEditText.getText().toString());
Double miDouble = toDouble(miEditText.getText().toString());
lResult.setText("" + Math.sqrt((hDouble * hDouble) + (bDouble * bDouble)));
}

Related

Display automatically an Integer value from Edit Text (entered by the user) to Text View without any actions (such as onButtonClick) in Android

Trying to get an integer from Edit Text entered by the user(such as Total Amount) and to display it by multiplying with value(such as 5%) and display it using TextView automatically.
For the 1st part i.e. simply displaying the integer from EditText to TextView got NumberFormatException Error.
'''
temp = (Integer.parseInt(editText.getText().toString()));
textView.setText(temp);
'''
And for the second part i.e. automatically displaying the value from EditText to TextView, no idea how to approach.
Just use textwatcher and put the logic in it. Just make sure change the id of edittext and textview
et.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
#Override
public void afterTextChanged(Editable s) {
String value = s.toString();
double outputValue = Integer.parseInt(value) * 0.05;
textView.setText(String.valueOf(outputValue));
}
});
Make sure in edittext that it only capture the numerical value.
you could try this approach
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) { }
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
#Override
public void afterTextChanged(Editable s) {
String userInputText = s.toString();
try {
val userInputAsNumbger = userInputText.toInt();
}catch (e:NumberFormatException){
print(e.message)
}
}
});
to ensure it doesn't error

How can I modify the input of multiple EditTexts at the same time, as I only modify one?

I have multiple EditTexts and I want to change the input of all of them at the same time, as I modify only one.(all of them take decimal numbers as input)
I stored the EditTexts in an array named 'editTexts'.
Here's what I tried
//Set the listener for each element
for (int i=0; i<editTexts.length; i++) {
final int finalI = i;
editTexts[i].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) {
//if the editText which is currently edited is empty, set the input for all the rest to be '0.0'
if (editTexts[finalI].getText().toString().trim().length() == 0) {
for(EditText e : editTexts) {
if (e == editTexts[finalI])
continue;
e.setText("0.0");
}
} else {
float no = Float.parseFloat(s.toString() + "");
//Set the input of all the other editTexts to be the decimal number entered, multiplied by 2
for(EditText e : editTexts){
if(e == editTexts[finalI])
continue;
e.setText(no*2+"");
}
}
}
#Override
public void afterTextChanged(Editable s) {
}
})
}
In this case the multiplication coefficient is just an example, it's not always gonna be 2. I used it just to test it out.
For some reason, when I change the input value, the app freezes.
Any help? Thanks!
Use LiveData to store your user input values.
Once it's value changes you can set value to each EditText. I think it is an easy way to implement.
Try it like this:
// et_x1, et_x2 and et_x3 are ids of EditTexts
//set inputType for all EditTexts as numberDecimal
EditText editText1 = findViewById(R.id.et_x1);
final EditText editText2 = findViewById(R.id.et_x2);
final EditText editText3 = findViewById(R.id.et_x3);
editText1.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) {
String value = s.toString();
double x;
if (!value.equals("")) {
x = Double.parseDouble(value);
} else {
x = 0.0;
}
editText2.setText(Editable.Factory.getInstance().newEditable((String.valueOf(Math.pow(x, 2)))));
editText3.setText(
Editable.Factory.getInstance().newEditable((String.valueOf(Math.pow(x, 3)))));
}
#Override
public void afterTextChanged(Editable s) {
}
});
Hope it helps you!

EditText can't set text the formatted string

I want to format my EditText after every typing.
(e.g: User types 1234 and I correct as 1.234,00)
With this function, I format String correctly and I can see it on Toast message. But whenever I try to set text to edittext, it gives error after typing second number.
This is my format function:
public String moneySeperator(double moneyAmount){
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator('.');
symbols.setDecimalSeparator(',');
DecimalFormat decimalFormat = new DecimalFormat("#,###.00", symbols);
String prezzo = decimalFormat.format(moneyAmount);
return prezzo;
}
Here is my EditText listener:
editText.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) {
}
#Override
public void afterTextChanged(Editable editable) {
editText.removeTextChangedListener(this);
if(!editText.getText().toString().isEmpty()){
String userInput = editText.getText().toString();
Toast.makeText(Denemey.this, ""+moneySeperator(Double.parseDouble(userInput)), Toast.LENGTH_SHORT).show();
editText.setText(""+moneySeperator(Double.parseDouble(userInput)));
}
editText.addTextChangedListener(this);
}
});
Here is the error: (It points editText.setText line)
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.incidijital.kdvtevkifati, PID: 7500
java.lang.NumberFormatException: For input string: "15,00"
at java.lang.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1306)
at java.lang.Double.parseDouble(Double.java:547)
at com.myproject.dd$1.afterTextChanged(Denemey.java:46)
UPDATED: I made my code really shorter. When I try a double like 1234.50
it works well on printing, but I think there is something wrong about afterTextChanged listener. My first 4 types (e.g: 1,234) works well, after I add more it crash because of Double.parseDouble casting, but there is no comma.
I removed formatter function.
#Override
public void afterTextChanged(Editable editable) {
editText.removeTextChangedListener(this);
java.text.NumberFormat formatter = java.text.NumberFormat.getInstance(java.util.Locale.GERMANY);
if(!editText.getText().toString().isEmpty()){
double myDob = Double.parseDouble(""+editable);
editText.setText(""+(formatter.format(myDob)));
editText.setSelection(editText.getText().length());
}
editText.addTextChangedListener(this);
}
});
You have to remove all non numeric chars before parsing it as double. I am assuming here that your #moneySeperator working fine for format .
editText.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) {
}
#Override
public void afterTextChanged(Editable editable) {
editText.removeTextChangedListener(this);
String userInput = editText.getText().toString().replaceAll("[^0-9]", "");
if(!userInput.isEmpty()){
Toast.makeText(Denemey.this, ""+moneySeperator(Double.parseDouble(userInput)), Toast.LENGTH_SHORT).show();
editText.setText(""+moneySeperator(Double.parseDouble(userInput)));
}else{
editText.setText("")
}
editText.addTextChangedListener(this);
}
});

My app crashes when value in text changed listener is deleted

when i deleted the values in e2 to make another calculation the app will crash because e4 and e5 are trying to perform calculations on a non number, what code shall i add?
private void hookButtons() {
e2 = findViewById(R.id.SalePriceNum);
e4 = findViewById(R.id.ebayFeeNum);
e5 = findViewById(R.id.paypalFeeNum);
e2.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) {
if (e2.getText().toString() != "")
{
double salePrice = Double.parseDouble(e2.getText().toString());
double ebayFee = salePrice / 10.00;
double paypalFee = (salePrice * 0.034) + 0.2;
double roundedPPFee = Math.round(paypalFee*100.00)/100.00;
double roundedEbayFee = Math.round(ebayFee*100.00)/100.00;
e4.setText(String.valueOf(roundedEbayFee));
e5.setText(String.valueOf(roundedPPFee));
}
}
});
}

How do I disable 2 buttons if a number field is empty

I have 2 buttons and 1 number field, if I press a button without something in the field, it crashes, so what I want to do is disable the buttons unless the number field has something in it, I have looked around for an answer but either they aren't relevant, or I'm not sure how it would fit into my code, here are the two onClick functions for each button. Thanks
public void toPounds(View view){
EditText amount = (EditText)findViewById(R.id.amount);
Double omrAmount = Double.parseDouble(amount.getText().toString());
Double gbrAmount = omrAmount * 1.79;
Toast.makeText(getApplicationContext(), "£" + gbrAmount.toString(), Toast.LENGTH_LONG).show();
}
public void toRiyals(View view){
EditText amount = (EditText)findViewById(R.id.amount);
Double gbrAmount = Double.parseDouble(amount.getText().toString());
Double omrAmount = gbrAmount / 1.79;
Toast.makeText(getApplicationContext(), omrAmount.toString() + " Riyals", Toast.LENGTH_LONG).show();
}
yourField.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(s.length() == 0)
button1.setEnabled(false)
else
button1.setEnabled(true)
}
});
link
If you want to disable buttons if edit text is empty then you can do the following :
EditText amount = (EditText)findViewById(R.id.amount);
Button button = (Button) findViewById(R.id.button1);
if(amount.getText().toString().isEmpty()){
button.setEnabled(false);
}
amount.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {}
#Override
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start,
int before, int count) {
if(s.length() == 0)
button1.setEnabled(false)
else
button1.setEnabled(true)
}
});
Not specifically an answer to your question, but generally speaking you would want to add some sort of check before you call your code which now crashes your application. It's not a good idea to to have code which crashes your app lingering around.
Maybe make a method like: isMyEditTextValid(...){..}

Categories