Updating editText values to get sum or difference

1.3k Views Asked by At

I have multiple EditText fields in which I would like to update according to the data in each one, so I'm using addTextChangedListener for them. My goal is to get the sum of two EditText values and display the answer in another EditText. However, I'm also trying to get the difference of the third EditText and one of the first two to display in the first. So amountreceived = totalprice + tip, I want to update accordingly, as well as if the user entered data into the total price and amount received, I would like it to be tip = amountreceived - totalprice.

My code is as follows:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.order_details);

    eAmountReceived = (EditText) findViewById(R.id.amountReceived);
    eTotalCost = (EditText) findViewById(R.id.orderTotal);
    eTip = (EditText) findViewById(R.id.tip);
    eMileage = (EditText) findViewById(R.id.mileage);
    eGrandTotal = (EditText) findViewById(R.id.grandTotal);

    eAmountReceived.addTextChangedListener(this);
    eTip.addTextChangedListener(this);

    // eTotalCost.addTextChangedListener(this);
    // eMileage.addTextChangedListener(this);
    // eGrandTotal.addTextChangedListener(this);

    eTip.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(eTip.isFocused() && isSet(eAmountReceived) && isSet(eTotalCost))
            {
                updateSubtract();
            }
        }

        @Override
        public void afterTextChanged(Editable s){}
    });

    eAmountReceived.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(eAmountReceived.isFocused() && isSet(eTotalCost) && isSet(eTip))
            {
                updateAdd();
            }
        }

        @Override
        public void afterTextChanged(Editable s){}
    });
}

private void updateAdd()
{
    double dTotalCost = Double.valueOf(eTotalCost.getText().toString());
    double dTip = Double.valueOf(eTip.getText().toString());
    eAmountReceived.setText(String.valueOf(dTotalCost + dTip));
}

private void updateSubtract()
{
    double dAmountReceived = Double.valueOf(eAmountReceived.getText().toString());
    double dTotalCost = Double.valueOf(eTotalCost.getText().toString());
    eTip.setText(String.valueOf(dAmountReceived - dTotalCost));
}

private boolean isSet(EditText editText)
{
    return !editText.getText().toString().matches("");
}

@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) 
{
    updateAdd();
    updateSubtract();
}

@Override
public void afterTextChanged(Editable editable) {}

public void onClick(View view)
{

    name = (EditText) findViewById(R.id.name);
    number = (EditText) findViewById(R.id.number);
    address = (EditText) findViewById(R.id.address);
    orderTotal = (EditText) findViewById(R.id.orderTotal);
    amountReceived = (EditText) findViewById(R.id.amountReceived);
    tip = (EditText) findViewById(R.id.tip);
    mileage = (EditText) findViewById(R.id.mileage);
    grandTotal = (EditText) findViewById(R.id.grandTotal);

    String cName = name.getText().toString();
    String num = number.getText().toString();
    String cAddress = address.getText().toString();
    String cOrderTotal = orderTotal.getText().toString();
    String cAmountReceived = amountReceived.getText().toString();
    String cTip = tip.getText().toString();
    String cMileage = mileage.getText().toString();
    String cGrandTotal = grandTotal.getText().toString();


    int id = db.addContact(new PhoneBook(cName, num, cAddress, cOrderTotal,
                                          cAmountReceived, cTip, cMileage, cGrandTotal));
    contactList.add(new PhoneBook(id, cName, num, cAddress, cOrderTotal,
                                   cAmountReceived, cTip, cMileage, cGrandTotal));
    adapter.notifyDataSetChanged();

    Toast.makeText(getApplicationContext(), "Entry Successfully Created.", Toast.LENGTH_LONG).show();
}

I thought this would work, but when I click on an EditText field to enter the data, the app crashes. I also have no errors in my logcat, so I don't know what I'm doing wrong. Any help would be greatly appreciated!

EDIT: The logcat error is as follows:

FATAL EXCEPTION: main


    Process: com.example.boley.databaseexample, PID: 2949
                            java.lang.NumberFormatException: Invalid double: ""
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.parseDouble(StringToReal.java:267)
at java.lang.Double.parseDouble(Double.java:301)
at java.lang.Double.valueOf(Double.java:338)
at com.example.boley.databaseexample.OrderDetails.updateAdd(OrderDetails.java:193)
at com.example.boley.databaseexample.OrderDetails.onTextChanged(OrderDetails.java:215)
at android.widget.TextView.sendOnTextChanged(TextView.java:7991)
at android.widget.TextView.handleTextChanged(TextView.java:8053)
at android.widget.TextView$ChangeWatcher.onTextChanged(TextView.java:10157)
at android.text.SpannableStringBuilder.sendTextChanged(SpannableStringBuilder.java:1033)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:559)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:492)
at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:491)
at android.text.method.NumberKeyListener.onKeyDown(NumberKeyListener.java:121)
at android.widget.TextView.doKeyDown(TextView.java:6098)
at android.widget.TextView.onKeyDown(TextView.java:5911)
at android.view.KeyEvent.dispatch(KeyEvent.java:2640)
at android.view.View.dispatchKeyEvent(View.java:9234)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2395)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1727)
at android.app.Activity.dispatchKeyEvent(Activity.java:2725)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315)
at com.android.internal.policy.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2310)
at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4127)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4089)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3820)
at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3981)
at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2253)
at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1874)
at android.view.inputmethod.InputMethodMan
1

There are 1 best solutions below

3
On

Your problem lies here in the way you are parsing your double values

private void updateSubtract() {
    double dAmountReceived = Double.valueOf(eAmountReceived.getText().toString());
    double dTotalCost = Double.valueOf(eTotalCost.getText().toString());
    eTip.setText(String.valueOf(dAmountReceived - dTotalCost));
}

If you change updateSubtract() and updateAdd() to something like this it should solve your problem. I just wrote this without testing but I'm sure it should be fine.

private void updateSubtract() {
    String amountReceivedText = eAmountReceived.getText().toString();
    String totalCostText = eTotalCost.getText().toString();

    if (!TextUtils.isEmpty(amountReceivedText) && !TextUtils.isEmpty(totalCostText)) {}
        float dAmountReceived = Float.parseFloat(amountReceivedText);
        float dTotalCost = Float.parseFloat(totalCostText);
        float dTipValue = dAmountReceived - dTotalCost;
        eTip.setText(String.valueOf(dTipValue));
    }
}

You should also make sure that you either check the input of eAmountReceived and totalCostTextto make sure it is a Float value or apply a inputType on your EditText so that it only takes float values as input. I prefer the latter because it gives you a numbers only keyboard when you focus on the EditText.