简体   繁体   中英

App crashes when “=” button is pressed when getText is empty - Android Studio

I have a calculator app that crashes when the equals button is pressed and there is nothing in the EditText that it getTexts from. I have looked at the other questions with similar situations, but those suggestions are not working. I am new to android and would like any help. I also have the issue if I have a "0" in my EditText.setText(), the "0" stays in front of the other numbers when they are pressed. Please let me know if you need more of the code to help.

Here is the Logcat info

09-08 07:58:32.915 13726-13726/com.ruthadeaton.bld3.calculator
E/AndroidRuntime: FATAL EXCEPTION: main Process: com.ruthadeaton.bld3.calculator, PID: 13726 java.lang.NumberFormatException: empty String
atsun.misc.FloatingDecimal.readJavaFormatString (FloatingDecimal.java:1842) at sun.misc.FloatingDecimal.parseFloat(FloatingDecimal.java:122) at java.lang.Float.parseFloat(Float.java:451) at com.ruthadeaton.bld3.calculator.MainActivity$26.onClick (MainActivity.java :346) at android.view.View.performClick(View.java:6597) at android.view.View.performClickInternal(View.java:6574) at android.view.View.access$3100(View.java:778) at android.view.View$PerformClick.run(View.java:25885) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6669) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

Here is my code:

buttonEqual.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mValueTwo=Float.parseFloat(edt1.getText() + "");
            if (mAddition == true) {
                edt1.setText(mValueOne + mValueTwo + "");
                mAddition=false;
            }
            if (mSubtract == true) {
                edt1.setText(mValueOne - mValueTwo + "");
                mSubtract=false;
            }

            if (mMultiplication == true) {
               edt1.setText(mValueOne * mValueTwo + "");
               mMultiplication=false;
            }

            if (mDivision == true) {
                edt1.setText(mValueOne / mValueTwo + "");
                mDivision=false;
            }
        }
    });

button0.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        edt1.setText(edt1.getText() + "0");
    }
});

buttonAdd.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
        mValueOne=Float.parseFloat(edt1.getText() + "");
        mAddition=true;
        edt1.setText(null);
    }
});

buttonSub.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mValueOne=Float.parseFloat(edt1.getText() + "");
        mSubtract=true;
        edt1.setText(null);
    }
});

buttonMul.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mValueOne=Float.parseFloat(edt1.getText() + "");
        mMultiplication=true;
        edt1.setText(null);
    }
});

buttonDivision.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        mValueOne=Float.parseFloat(edt1.getText() + "");
        mDivision=true;
        edt1.setText(null);
     }
});

It can't do a

mValueTwo=Float.parseFloat(edt1.getText() + "");

if edt1.getText() is empty. You can correct this using a try-catch.

buttonEqual.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            try{
                mValueTwo=Float.parseFloat(edt1.getText() + "");

                if (mAddition == true) {

                    edt1.setText(mValueOne + mValueTwo + "");
                    mAddition=false;
                }

                if (mSubtract == true) {
                    edt1.setText(mValueOne - mValueTwo + "");
                    mSubtract=false;
                }

                if (mMultiplication == true) {
                    edt1.setText(mValueOne * mValueTwo + "");
                    mMultiplication=false;
                }

                if (mDivision == true) {
                    edt1.setText(mValueOne / mValueTwo + "");
                    mDivision=false;
                }
            }catch(Exception e){
                //eventually logging here
            } 
        }
   });

Else you can make some controls before doing the parseFloat

buttonEqual.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
            String edt = edt1.getText().toString();
            if(edt.matches("")){
                //something like a toast to signal
            }else{
                   mValueTwo=Float.parseFloat(edt1.getText() + "");

                    if (mAddition == true) {

                        edt1.setText(mValueOne + mValueTwo + "");
                        mAddition=false;
                    }

                    if (mSubtract == true) {
                        edt1.setText(mValueOne - mValueTwo + "");
                        mSubtract=false;
                    }

                    if (mMultiplication == true) {
                        edt1.setText(mValueOne * mValueTwo + "");
                        mMultiplication=false;
                    }

                    if (mDivision == true) {
                        edt1.setText(mValueOne / mValueTwo + "");
                        mDivision=false;
                    }
                }
            }
       });

You can set a hint attribute in your edit text that way it disappears anytime a number is actually inserted.

android:hint="0"

Also for the 0 being in front, maybe you want your edit text to be of the number format

android:inputType = "numberDecimal"

You didn't paste a stacktrace of the crash but I will assume it's a null pointer exception

if (edt1.getText != null) { /* do whatever executions */}

I have a calculator app that crashes when the equals button is pressed and there is nothing in the EditText that it getTexts from.

Because you do not validate the input from users is valid or not. Obviously empty string is not a number that why the app crashes with NumberFormatExecption .

I also have the issue if I have a "0" in my EditText.setText(), the "0" stays in front of the other numbers when they are pressed.

You can use TextWatcher to update the text view based on input from users.

I will guide you step by step how to fix those issues

First, define a method which validates input from users is a valid number or not.

private boolean isValidNumber(String numberInString) {
    try {
        Float.parseFloat(numberInString);
        return true;
    } catch (NumberFormatException e) {
        return false;
    }
}

Second, each time users press on a arithmetic operator (+, -, *, /) or equal (=) the app will get value from the edt1 . Then write a method to do that to avoid duplicate code.

/**
 * Get current input from user and try parse it to a number.
 *
 * @return a number if input is valid, otherwise return null.
 */
private Float getInputValue() {
    Float possibleNumber = null;
    String numberInString = edt1.getText().toString();
    if (isValidNumber(numberInString)) {
        possibleNumber = Float.parseFloat(numberInString);
    }
    return possibleNumber;
}

Third, prevent user from adding more than one zero number by using TextWatcher .

edt1.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) {
        String content = s.toString();
        if (content.startsWith("0") && content.length() == 2 && Character.isDigit(content.charAt(1))) {
            edt1.setText(String.valueOf(content.charAt(1)));
            edt1.setSelection(1);
        }
    }
});

Finally put it together.

public class MainActivity extends AppCompatActivity {

    // Your variables here
    ...

    // Make these two variables is Float instead of float.
    Float mValueOne;
    Float mValueTwo;

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

        // Your init view here
        ...

        edt1.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) {
                String content = s.toString();
                if (content.startsWith("0") && content.length() == 2 && Character.isDigit(content.charAt(1))) {
                    edt1.setText(String.valueOf(content.charAt(1)));
                    edt1.setSelection(1);
                }
            }
        });

        buttonEqual.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValueTwo = getInputValue();
                if (mValueOne == null || mValueTwo == null) {
                    // One of there or both of two values are not valid then do nothing.
                    return;
                }

                if (mAddition) {
                    edt1.setText(String.valueOf(mValueOne + mValueTwo));
                    mAddition = false;
                }

                if (mSubtract) {
                    edt1.setText(String.valueOf(mValueOne + mValueTwo));
                    mSubtract = false;
                }

                if (mMultiplication) {
                    edt1.setText(String.valueOf(mValueOne + mValueTwo));
                    mMultiplication = false;
                }

                if (mDivision) {
                    edt1.setText(String.valueOf(mValueOne + mValueTwo));
                    mDivision = false;
                }
            }
        });

        button0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                edt1.setText(String.valueOf(edt1.getText().toString() + "0"));
                edt1.setSelection(edt1.getText().length());
            }
        });

        buttonAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValueOne = getInputValue();
                mAddition = true;
                edt1.setText(null);
            }
        });

        buttonSub.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValueOne = getInputValue();
                mSubtract = true;
                edt1.setText(null);
            }
        });

        buttonMul.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValueOne = getInputValue();
                mMultiplication = true;
                edt1.setText(null);
            }
        });

        buttonDivision.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mValueOne = getInputValue();
                mDivision = true;
                edt1.setText(null);
            }
        });
    }

    /**
     * Get current input from user and try parse it to a number.
     *
     * @return a number if input is valid, otherwise return null.
     */
    private Float getInputValue() {
        Float possibleNumber = null;
        String numberInString = edt1.getText().toString();
        if (isValidNumber(numberInString)) {
            possibleNumber = Float.parseFloat(numberInString);
        }
        return possibleNumber;
    }

    private boolean isValidNumber(String numberInString) {
        try {
            Float.parseFloat(numberInString);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM