Sum of all numbers entered in a listview's edittext - java

I have a listview in my activity with a textview and an edittext of inputType number, the user will enter numbers in each edit text.There is a textview which displays the sum of all the numbers entered. How do i calculate the sum and show it in the textview as soon as the user enters the amount.
I tried it this way :
holder.tvDonationAmount.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean b) {
try {
amount = Integer.parseInt(holder.tvDonationAmount.getText().toString());
} catch (NumberFormatException e) {
e.printStackTrace();
}
addn_array.add(amount);
for (int j = 0; j < addn_array.size(); j++) {
try {
sum += addn_array.get(j);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
});
I tried adding each element after he's entered the number into an Arraylist of Integers and add the elements which throws the error.
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference
at the line inside for loop sum+ = . .
I also implemented this in my Textwatcher like this
private TextWatcher watcher = 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) {
try {
amount = Integer.parseInt(holder.tvDonationAmount.getText().toString());
addn_array.add(amount);
} catch (NumberFormatException e) {
e.printStackTrace();
}
Toast.makeText(context, ""+addn_array.get(0), Toast.LENGTH_SHORT).show();
for (int j = 0; j <addn_array.size(); j++) {
try {
sum += addn_array.get(j);
Toast.makeText(context, ""+sum, Toast.LENGTH_SHORT).show();
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
Toast.makeText(context, "" + sum, Toast.LENGTH_SHORT).show();
}
};`
It throws this error.
[![Logcat][1]][1]
Can you please tell me what's wrong with this or can you please suggest any better way if there's any?

Take a look at TextWatchers. You don't need a focus change listener, but a TextWatcher, since it listens to changes you make to the text inside the EditText.
Here is a great example: http://stacktips.com/tutorials/android/android-textwatcher-example

The problem is that in case a NumberFormatException is thrown when parsing amount, amount can be null. Thus, null is added to the list.
try {
amount = Integer.parseInt(holder.tvDonationAmount.getText().toString());
addn_array.add(amount);
} catch (NumberFormatException e) {
e.printStackTrace();
}
This will solve your NullPointerException.
Please do use a TextWatcher like #Gregorio Palamà suggested.

Related

How to show result with Int on calculator?

I am making the calculator app. It shows double at the result even when I don't use double.
Example) 1+1 = 2.0
But I want like 1+1= 2
Of course, I want to keep double when there is double like 1.2+1.3= 2.5
How should I have to edit?
I tried to edit like this, but there is an error.
public void equalsOnClick(View view)
{
Integer result = null;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");
try {
result = (int)engine.eval(workings);
} catch (ScriptException e)
{
Toast.makeText(this, "Invalid Input", Toast.LENGTH_SHORT).show();
}
if(result != null)
resultsTV.setText(String.valueOf(result.intValue()));
}
MainActivity
public class MainActivity extends AppCompatActivity {
TextView workingsTV;
TextView resultsTV;
String workings = "";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initTextView();
}
private void initTextView()
{
workingsTV = (TextView)findViewById(R.id.workingsTextView);
resultsTV = (TextView)findViewById(R.id.resultTextView);
}
private void setWorkings(String givenValue)
{
workings = workings + givenValue;
workingsTV.setText(workings);
}
public void equalsOnClick(View view)
{
Double result = null;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");
try {
result = (double)engine.eval(workings);
} catch (ScriptException e)
{
Toast.makeText(this, "Invalid Input", Toast.LENGTH_SHORT).show();
}
if(result != null)
resultsTV.setText(String.valueOf(result.doubleValue()));
}
public void clearOnClick(View view)
{
workingsTV.setText("");
workings = "";
resultsTV.setText("");
leftBracket = true;
}
}
It is happening because you have declared result of type, Double. Therefore, until you cast it's doubleValue() into an int and set the same to resultsTV, its double value will be set there.
Change your method definition as follows:
public void equalsOnClick(View view) {
Double result = null;
ScriptEngine engine = new ScriptEngineManager().getEngineByName("rhino");
try {
result = (Double)engine.eval(workings);
if(result != null) {
int intVal = (int)result.doubleValue();
if(result == intVal) {// Check if it's value is equal to its integer part
resultsTV.setText(String.valueOf(intVal));
} else {
resultsTV.setText(String.valueOf(result));
}
}
} catch (ScriptException e) {
Toast.makeText(this, "Invalid Input", Toast.LENGTH_SHORT).show();
}
}
Note that I have also moved resultsTV.setText inside the try-catch block so that it gets executed only when result = (Double)engine.eval(workings) does not throw an exception.
Use the modulo operator to check whether a double is an Integer
(result %1 ==0)
or Math.floor then check whether result changed or not.
If it is, you can use Integer.valueOf(result)
Integer has a built in toString method by the way.
Nothing to do.
Just check the string on whether it ended with ".0"
If so, just replace the string like this: replace(".0","");
In the else condition, insert the string as you input like now.

Handlers don't end after calling removeCallbacksAndMessages(null)

I have two handlers. Handler in a handler. Both of them are in a for-loop.
The overview is something like this,
for{
handler.postDelayed(runnableA{
for{
handler2.postDelayed(runnableB{
function();
}, 3000);
}
}, 1000);
}
I wanted to end handlers' work at any time when the user clicks back button. So, I created two Runnable Classes so that I can use something like runnableA.removellbacksAndMessages(null).
Handler messageHandler;
Handler countDownHandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toast.makeText(this, "Start Play in 5 seconds", Toast.LENGTH_SHORT).show();
countDownHandler = new Handler();
for (int i = 7; i >= 0; --i) {
final int idx = i;
Runnable countRunnable = new CountRunnable(idx, countDownView);
countDownHandler.postDelayed(countRunnable, 1000 * (7 - i));
}
}
And this is Runnable Classes.
public class CountRunnable implements Runnable {
int idx;
TextView countDownView;
public CountRunnable(int idx, TextView countDownView) {
this.idx = idx;
this.countDownView = countDownView;
}
#Override
public void run() {
int messageSize = messageItems.size();
for (int j = 0; j < messageSize; j++) {
final int jdx = j;
messageHandler = new Handler();
Runnable messageRunnable = new MessageRunnable(jdx);
messageHandler.postDelayed(messageRunnable, 3000 * jdx);
}
}
}
class MessageRunnable implements Runnable {
int jdx;
public MessageRunnable(int jdx) {
this.jdx = jdx;
}
#Override
public void run() {
addMessageView(messageItems.get(jdx));
}
}
This is onBackPressed():
#Override
public void onBackPressed() {
super.onBackPressed();
Toast.makeText(getApplicationContext(), "All Work Ended.", Toast.LENGTH_SHORT).show();
scrollFlag = true;
try {
messageHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
Log.d(TAG, "messageHandler never used");
e.printStackTrace();
}
try {
countDownHandler.removeCallbacksAndMessages(null);
} catch (Exception e) {
e.printStackTrace();
}
}
public void addMessageView(String message){
try{
mTextView.setText(message);
}catch(Exception e){
Toast.makeText(getApplicationContext(), "Abnormal End", Toast.LENGTH_SHORT).show();
}
}
But, I keep getting errors because the activity already ended but the handlers can't find the activity. So, Abnormal End Toast message shows as many as the size of inner for loop.
I can ignore this if I don't use the Toast message, but I am afraid of Memory leak or Bad formed Program or something like that.
How can I fix this problem?
The main problem is that you are creating n numbers of CountRunnables and m number MessageRunnables. Despite creating more than one numbers of handlers you are removing callbacks only for the latest-created Hanlder.
Here's what you should do:
Keep a reference of all the Handlers and Runnables and call messageHandler.removeCallbacksAndMessages(null); and countDownHandler.removeCallbacksAndMessages(null); on all of them.

How to add number separators in EditText

I have an Edittext and want to set the EditText so that when the user is inputting the number to be converted, a thousand separator (,) should be added automaticaaly in realtime to the number .but i want do this in "onTextChanged" method not in the "afterTextChanged" method. How can I?
public class NumberTextWatcherForThousand implements TextWatcher {
EditText editText;
public NumberTextWatcherForThousand(EditText editText) {
this.editText = editText;
}
#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 view) {
String s = null;
try {
// The comma in the format specifier does the trick
s = String.format("%,d", Long.parseLong(view.toString()));
edittext.settext(s);
} catch (NumberFormatException e) {
}
}
Try this code:
et.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// TODO Auto-generated method stub
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
et.removeTextChangedListener(this);
try {
String givenstring = s.toString();
Long longval;
if (givenstring.contains(",")) {
givenstring = givenstring.replaceAll(",", "");
}
longval = Long.parseLong(givenstring);
DecimalFormat formatter = new DecimalFormat("#,###,###");
String formattedString = formatter.format(longval);
et.setText(formattedString);
et.setSelection(et.getText().length());
// to place the cursor at the end of text
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
et.addTextChangedListener(this);
}
});
I use a TextWatcher to trig on every change in EditText, and use this code to separate currency sections and then set to EditText after every character changes:
public static String formatCurrencyDigit(long amount) {
return String.format("%,d%s %s", amount, "", "");
}

Automatic check and calculations not working

I'm creating a PV = nRT calculator that has the user enter any of the three given variables. Without the use of a button, the program will automatically detect that three variables have been given and will calculate the fourth missing variable automatically. This is my code so far:
Thread calculate = new Thread(new Runnable() {
#Override
public void run() {
try {
if (Calculations.isCalcable(pressure.getText().toString(),
volume.getText().toString(),
moles.getText().toString(),
temperature.getText().toString()) == true) {
if (pressure.getText().toString().length() == 0) {
pressure.setText("1010");
} else if (volume.getText().toString().length() == 0) {
volume.setText("1010");
} else if (moles.getText().toString().length() == 0) {
moles.setText("1010");
} else {
temperature.setText("1010");
}
}
} catch (Exception e){
}
}
});
calculate.start();
This doesn't work. Also I'm not sure if I'm actually supposed to use a Thread or not. Here's what happens when I enter three variables (The R variable is a constant):
Imgur
In this case the Temperature text should've changed to "1010".
Here's my isCalcable class:
public class Calculations {
public static boolean isCalcable (String pressure, String volume, String moles, String temperature){
int hasNumber = 0;
if (pressure.length() > 0){
hasNumber++;
}
if (volume.length() > 0){
hasNumber++;
}
if (moles.length() > 0){
hasNumber++;
}
if (temperature.length() > 0){
hasNumber++;
}
if (hasNumber == 3){
return true;
}
return false;
}
}
What do I do?
What you need is to detect whether value has been inputted on the
text fields right? Then have you looked at TextWatcher?
Here is an example on how to use it.
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//code
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
//code
}
#Override
public void afterTextChanged(Editable s) {
//code
}
});
Basically you apply the TextWatcher to the three fields and watch.
If all three fields have the values you need, then do the calculation.
Maybe you can add global variables to the activity and check these global variables on the onTextChanged() method of the text field, and if three of the variables are already complete, set the value of the fourth one.

How to get text from EditText into integer variable

i try to get the the value of the text from the EditText as an integer number , but i found that every time i insert any value it calculate the initialized value from the catch , so what's the solved for this problem
the result become =0
public Button bu,bu2,bu3,bu4,bu5;
int num=0,num2=0,num3=0,result=0;
public EditText on,on2,on3,on4;
public TextView tex ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monthlycalc);
bu=(Button)findViewById(R.id.year);
bu.setOnClickListener(this);
bu2=(Button)findViewById(R.id.calc);
bu2.setOnClickListener(this);
bu3=(Button)findViewById(R.id.reset);
bu3.setOnClickListener(this);
bu4=(Button)findViewById(R.id.H1);
bu4.setOnClickListener(this);
bu5=(Button)findViewById(R.id.ron);
bu5.setOnClickListener(this);
try {
on=(EditText)findViewById(R.id.loanAm);
num=Integer.valueOf(on.getText().toString().trim());
} catch (NumberFormatException e) {
num=0;
}
try {
on2=(EditText)findViewById(R.id.intRate);
num2=Integer.valueOf(on2.getText().toString().trim());
} catch (NumberFormatException e) {
num2=0;
}
try {
on3=(EditText)findViewById(R.id.lonTerm);
num=Integer.valueOf(on3.getText().toString().trim());
} catch (NumberFormatException e) {
num3=0;
}
tex = (TextView) findViewById(R.id.monPay);
result=num+num2+num3;
#Override
public void onClick(View v)
{
if (v.getId()==R.id.calc)
tex.setText(String.valueOf(result));
}
Move your code to onClick
You are trying to get the values inside onCreate which happens while the activity is being launched and all EditTexts are empty, put it inside the onClick and it will work :)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_monthlycalc);
bu=(Button)findViewById(R.id.year);
bu.setOnClickListener(this);
bu2=(Button)findViewById(R.id.calc);
bu2.setOnClickListener(this);
bu3=(Button)findViewById(R.id.reset);
bu3.setOnClickListener(this);
bu4=(Button)findViewById(R.id.H1);
bu4.setOnClickListener(this);
bu5=(Button)findViewById(R.id.ron);
on=(EditText)findViewById(R.id.loanAm);
on2=(EditText)findViewById(R.id.intRate);
on3=(EditText)findViewById(R.id.lonTerm);
tex = (TextView) findViewById(R.id.monPay);
}
#Override
public void onClick(View v)
{
try {
num=Integer.valueOf(on.getText().toString().trim());
} catch (NumberFormatException e) {
num=0;
}
try {
num2=Integer.valueOf(on2.getText().toString().trim());
} catch (NumberFormatException e) {
num2=0;
}
try {
num=Integer.valueOf(on3.getText().toString().trim());
} catch (NumberFormatException e) {
num3=0;
}
result=num+num2+num3;
if (v.getId()==R.id.calc)
tex.setText(String.valueOf(result));
}
Because you have maybe Chars or Whitespaces in your String which are not numeric.
Parse it using regex.
final Pattern pattern = Pattern.compile("\\d+"); // the regex
final ArrayList<Integer> ints = new ArrayList<Integer>(); // results
while (matcher.find()) { // for each match
ints.add(Integer.parseInt(matcher.group())); // convert to int
}
If you really want to remove all whitespaces dont use trim. Use
st.replaceAll("\\s+","")
which removes all tabs aswell
And make sure that your values are grabbed when you click the button, not before, since it dont have any values inside while initializing, if you dont define a defaultValue.

Categories

Resources