I am creating a calculator app in android. The issue is how can I check for existence of two decimals in a single numeric value . Currently my calculator allows inputs such as 1.2.3 which is illegal . It must allow a decimal if an operator has been used. Eg 1.1+2.2 is legal but 1.1.1+2.2 isn't.
Here is my code for decimal handling:
public class TrialCalculator extends AppCompatActivity implements Button.OnClickListener {
Button btn1, btn2, btnBack, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn0, btnPlus, btnMinus, btnMul, btnDiv, btnEquals, btnClear, btnDecimal, btnPercent;
EditText calcResult;
double number = 0;
private char opcode = '1';
private void handleDecimal() {
if (opcode == 0) clear();
if (calcResult.getText() == null) {
calcResult.setText("0.");
calcResult.setSelection(2);
} else {
String txt = calcResult.getText().toString();
if (txt.lastIndexOf(".")<txt.length()-1) {
calcResult.append(".");
}
}
}
}
I am calling the buttonDot from onClick Method.
One solution is to have a flag which keeps track of the decimal:
class MyCalculator {
private hasDecimal = false;
// ...
}
Set this flag to true the first time that the user types a decimal. Then check the flag to see if a decimal has been previously typed.
Of course, this only works if you are responding to each key press directly rather than getting the entire input from a EditText after the user has typed the entire number.
You can use regex with matches function
\\d* mean match zero or more digits
(\\.\\d+)? match a . followed by one or more digits , ? mean matches between zero or one times of given group
Regex Demo : note with matches function in java, we don't need ^ start and $ ending anchors
Code
if (txt.matches("\\d*(\\.\\d+)?")) {
// number has one decimal
}
else{
// number has more than one decimal
}
Note: if you don't want to allow values like .5 then use \\d+ instead of \\d* as
\\d+(\\.\\d+)?
As suggested by #Code-Apprentice , if you want to accept values like 4343. etc
you can use
\\d*(\\.\\d*)?
Using text watcher
calcResult.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) {
boolean flag = s.toString().matches("\\d*(\\.\\d*)?");
if(!flag){
// calcResult.setError...
// you display a toast
}
}
});
Update : To match multiple values with operators , you can use
(\\d*(\\.\\d*)?([+\\-*%\\]|$))*
RegEx demo
Test Cases
String pat="(\\d*(\\.\\d*)?([+\\-*%\\]|$))*";
System.out.println("4.5-3.3+3.4".matches(pat));
System.out.println(".5".matches(pat));
System.out.println("4".matches(pat));
System.out.println("4.5.5-4.4".matches(pat));
System.out.println("4.44.5+4.4.4".matches(pat));
System.out.println("4.".matches(pat));
Output :
true
true
true
false
false
true
lastIndexOf returns -1 if the character is not found in the string. So your condition txt.lastIndexOf(".")<txt.length()-1 is always true. You could change it to
txt.lastIndexOf(".") == -1
To check for existence of two decimals in a single no then split the string by decimal.
for e.g.,
String txt = calcResult.getText().toString();
String[] decimals = txt.split("\\.");
if(decimals.length > 2) {
// txt contains more than 1 decimal.
// Your logic ..
}
Related
I am building a calculator app and everything is working properly but I don't know the code for backspace.
public class MainActivity extends AppCompatActivity {
// UI Elements
private TextView num_input;
private TextView num_input;
private ImageButton num_backspace;
private float input, input2 ;
boolean Addition, Subtract, Multiplication, Division, mRemainder, decimal, add_sub;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initializing
num_input = findViewById(R.id.num_input);
num_output = findViewById(R.id.num_output);
num_backspace = findViewById(R.id.num_backspace);
num_backspace.setOnClickListener(new View.OnClickListener() {
#Override
//TODO: the backslash code goes here.
});
}
}
I tried doing this👇🏻
num_backspace.setOnClickListener(new View.OnClickListener() {
#Override
input = Float.parseFloat(num_input.getText() + "");
String sample_input = Float.toString(input);
sample_input = sample_input.substring(0,sample_input.length() - 1);
});
Some help would be great!
thanks in advance
It's better to store input as a String, not float. Because before you start doing mathematical calculations it's just a String input, and "backspace" means basically removing one character, it's not a mathematical operation. So, provided input is a String, backspace code will be:
input = input(0, input.length() - 1);
num_input.setText(input);
And before doing calculations convert your String input into float via
float operand = Float.parseFloat(input);
Put this code inside your setOnClickListener
String value = num_input.getText().toString();
if (value != null && value.length() > 0 ) {
value = value.substring(0, value.length() - 1);
}
num_input.setText(value);
How this is usually done is getting the current value (entered number) in the TextView, remove the last character from the string and writing it back to the TextView.
I'm using an EditText Field where the user can specify an amount of money.
I set the inputType to numberDecimal which works fine, except that this allows to enter numbers such as 123.122 which is not perfect for money.
I wrote some custom InputFilter method and it's working like this .User can 5 elements before dot and after dot-two,but not working correctly
My goals are :
1) use should input maximum 9999.99
2) If user starting from 0 and second element is also 0,It must replace with .(for example 0.0) and after two elements after dot(like this 0.01)
here is a my code
public class DecimalDigitsInputFilter implements InputFilter {
Pattern mPattern;
public DecimalDigitsInputFilter(int digitsBeforeZero,int digitsAfterZero) {
mPattern=Pattern.compile("[0-9]*" + (digitsBeforeZero-1) + "}+((\\.[0-9]*" + (digitsAfterZero-1) + "})?)||(\\.)?");
}
#Override
public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
Matcher matcher=mPattern.matcher(dest);
if(!matcher.matches())
return "";
return null;
}
}
I'm calling this method like this
amountValue.setFilters(new InputFilter[] {new DecimalDigitsInputFilter(5,2)});
How I can rewrite my code to solved my issues ?
thanks
Your constructed regex is all wrong.
The first part of your regex is this expression:
"[0-9]*" + (digitsBeforeZero-1) + "}+"
Say digitsBeforeZero = 5, that gets you:
[0-9]*4}+
That's not the correct regex. The regex is supposed to be:
[0-9]{1,5}
meaning between 1 and 5 digits.
I have made an app where the user selects a food type, enters a weight and then the app calculates the calories. This calorie is then moved onto the MainActivity (when the 'Save' button is pressed) where the total calories will be displayed for that day.
I need the app to take all calories calculated and add them onto any existing values on the main activity. I wrote the code below, however the app crashes when I press the save button my second activity.
String greeting = getIntent().getStringExtra("Greeting Message");
EditText editText1 = (EditText)findViewById(R.id.editText1);
String value = editText1.getText().toString();
Integer aValue = (value != null && !value.isEmpty()) ? Integer.parseInt(value) : 0 ;
Integer bValue = (greeting != null && !greeting.isEmpty()) ? count +=Integer.parseInt(greeting) : 0 ;
editText1.setText(count + "");
Stack Error:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.nicola.student.mealtracker/com.nicola.student.mealtracker.MainActivity}: java.lang.NumberFormatException: Invalid int: "70.0Cal"
You should check Your value String, Your exception tells me that the String is "70.0Cal". First, You can get a substring, if You know that the last three signs are allways "Cal"
String value = value.substring(0,substring.length()-3);
and second, You have a decimal value, so You should use not integer, You should use Float or double.
also, You should check if the text in the EditText is not null or empty:
String edittextText = editText1.getText().toString();
if(edittextText!=null && !edittextText.equals("")){
//start calculating
}
Either value, or greeting has a value that cannot be converted to int : "70.0Cal".
So remove the suffic "Cal" , and if you have to deal with fractions, use double instead of int.
Looking at the short stack trace provided I can see that you are parsing a String value that is not in a correct Integer format.
You will have to do some validation on the field to make sure that the input provided is a valid numeric value. You can do that by using the following method or by setting the EditText inputType android:inputType="number"
/**
* Checks if the text is a valid numeric value
* #param value
* #return valid
*/
public static boolean isNumeric(String value) {
if (!isNull(value)) {
if (value.matches("[-+]?\\d*\\.?\\d+")) {
return true;
}
}
return false;
}
I would suggest not appending Cal to the value returned. Keep the input numeric. Rather add the "Cal" value in a TextView next to your EditText.
Implement it this way by using the isNumeric method to check the value before parsing.
public void executeYourCode() {
//Parse your values to Double
//as you are using Double values
Double aValue = getCheckedValue(value) ;
Double bValue = getCheckedValue(greeting);
count+= bValue;
editText1.setText(String.valueOf(count));
}
public int getCheckedValue(String value) {
if (value != null && !value.isEmpty() && isNumeric(value)) {
return Double.parseDouble(value.trim());
}
return 0;
}
I want an editText that only allows text input from A to z, no numbers or other characters. I've found out I have to use InputFilter but I don't understand how this code works.
InputFilter filter = new InputFilter() {
public CharSequence filter(CharSequence source, int start, int end,
Spanned dest, int dstart, int dend) {
for (int i = start; i < end; i++) {
if (!Character.isLetterOrDigit(source.charAt(i))) {
return "";
}
}
return null;
}
};
edit.setFilters(new InputFilter[]{filter});
The code you posted adds a custom filter to the EditText field. It checks to see if the character entered is not a number or digit and then, if so, returns an empty string "". That code is here:
if (!Character.isLetterOrDigit(source.charAt(i))) {
return "";
}
For your needs, you want to change the code slightly to check if the character is NOT a letter. So, just change the call to the static Character object to use the isLetter() method. That will look like this:
if (!Character.isLetter(source.charAt(i))) {
return "";
}
Now, anything that is not a letter will return an empty string.
Haven't actually done it, but check Androids NumberKeyListener. You can find the source code for it here:
http://www.java2s.com/Open-Source/Android/android-core/platform-frameworks-base/android/text/method/NumberKeyListener.java.htm
it does exactly the opposite of what you need, but that should be a good enough starting point.
Making a simple app for my android.
in my xml interface there is a text box in which the user will input a number (for example: 10). the id of this text box is "input1"
how do I call the value of input1 in java and then perform a calculation on it?
For example...
suppose input1 = x
x + 5 or x*2
and for that matter, how do I have the resulting value appear as constantly updated text output in a specified place on the UI?
In the Activity where you are using this layout XML, you would do this:
private EditText input;
private EditText result;
public void onCreate(Bundle b) {
setContentView(R.layout.my_activity);
// Extract the text fields from the XML layout
input = (EditText) findById(R.id.input1);
result = (EditText) findById(R.id.result);
// Perform calculation when input text changes
input.addKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keycode, KeyEvent keyevent) {
if (keyevent.getAction() == KeyEvent.ACTION_UP) {
doCalculation();
}
return false;
}
});
}
private void doCalculation() {
// Get entered input value
String strValue = input.getText().toString;
// Perform a hard-coded calculation
int result = Integer.parseInt(strValue) * 2;
// Update the UI with the result
result.setText("Result: "+ result);
}
Note that the above includes no error handling: it assumes that you have restricted the input1 text field to allow the input of integer numbers only.
In your XML you can also set android:inputType="number" to only allow numbers as entries.