Android Tip,Tax,Total Calculator - java

Hello I am new too Java and learning how to built android apps.
I have this calculator that I have been working on I need help in figuring out how to set value to EditText. When user types in CA, OR, or FL in the EditText how would I assign the value to it? CA = 7% , OR = 8% and FL = 10% thanks
public void calculate(View view) {
EditText billET = findViewById(R.id.edit_bill_amount);
EditText tipPercentET = findViewById(R.id.edit_tip_percent);
EditText taxPercentET = findViewById(R.id.edit_tax_percent);
String billString = billET.getText().toString();
String tipPercentString = tipPercentET.getText().toString();
String taxPercentString = taxPercentET.getText().toString();
float bill = Float.parseFloat(billString);
int tipPercent = Integer.parseInt(tipPercentString);
int taxPercent = Integer.parseInt(taxPercentString);
TipCalculator tc = new TipCalculator(tipPercent / 100.0F, bill, taxPercent / 100.0F);
float taxAmount = tc.taxAmount();
float tipAmount = tc.tipAmount();
float total = tc.totalAmount();
TextView taxAmountTV = findViewById(R.id.label_tax_amount_value);
TextView tipAmountTV = findViewById(R.id.label_tip_amount_value);
TextView totalAmountTV = findViewById(R.id.label_total_amount_value);
taxAmountTV.setText(taxAmount + "");
tipAmountTV.setText(tipAmount + "");
totalAmountTV.setText(total + "");
}

You can use TextWatcher for it.
TextWatcher watcher;
watcher=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) {
edittext.removeTextChangedListener(watcher);
switch(s.toString){
case "CA" :
edittext.setText("7%");
case "OR" :
edittext.setText("8%");
case "FL" :
edittext.setText("10%");
}
edittext.addTextChangedListener(watcher);
}
};
edittext.addTextChangedListener(watcher);

The implementation would be something like this
EditText editText = findViewById(R.id.editText);
if (editText.getText().toString().equals("CA")) {
textView.setText("CA=7%");
}

You can store those percentages to static variables and then assign them. If I'm getting your issue correctly a possible solution would be the following:
//outside of the calculate method
protected static String CA_PERCENTAGE = "CA = 7%";
protected static String OR_PERCENTAGE = "OR = 8%";
protected static String FL_PERCENTAGE = "FL = 10%";
//inside your calculate method
switch(area){
case "CA" :
tipAmountTV.setText(CA_PERCENTAGE);
case "OR" :
tipAmountTV.setText(OR_PERCENTAGE);
case "FL" :
tipAmountTV.setText(FL_PERCENTAGE);
}
of course this is not the "prettiest" thing to do but since you're new to Java you get to play with the switch statement.

Related

Convert formatCurrency (rupiah) to int

Here I have a method like this:
// method currency format
private String formatRupiah(Double number) {
Locale locale = new Locale("IND", "ID");
NumberFormat numberFormat = NumberFormat.getCurrencyInstance(locale);
String formatRupiah = numberFormat.format(number);
String[] split = formatRupiah.split(",");
int length = split[0].length();
String formatRupiahString = split[0].substring(0, 2) + " " + split[0].substring(2, length);
return formatRupiahString;
}
And also have this method to change the text that is in the edit text into the currency format:
private void editTextToFormatCurrency() {
etJumlah.addTextChangedListener(new TextWatcher() {
private String jumlahFormat = Objects.requireNonNull(etJumlah.getText()).toString().trim();
#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.toString().equals(jumlahFormat)) {
etJumlah.removeTextChangedListener(this);
String replace = s.toString().replaceAll("[Rp. ]", "");
if (!replace.isEmpty()) {
jumlahFormat = formatRupiah(Double.parseDouble(replace));
} else {
jumlahFormat = "";
}
etJumlah.setText(jumlahFormat);
etJumlah.setSelection(jumlahFormat.length());
etJumlah.addTextChangedListener(this);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
And now my question is how to change TextToFormatCurrencycto int or Integer without format currency ?
My goal of changing back to Integer or int is so I can upload to Firestore with data type number.
And the answer:
https://www.youtube.com/watch?v=TdgQW8T-KeQ&t (this is my video)
https://www.youtube.com/watch?v=NQOK2cam3js&t (this is my inspiration video)
String jumlahString = Objects.requireNonNull(String.valueOf(layoutJumlah.getEditText().getText()));
jumlahString = jumlahString.replaceAll("[^0-9]", "");
jumlah = Integer.parseInt(jumlahString);

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!

Adding value on multiple EditText and getting the Total on every textchange

How can I sum all the total of my multiple EditText without using a Button but only on TextWatcher's onTextChanged() method. assuming this is my layout:
EditText1 = 5
EditText2 = 5
EditText3 = 5
EditText4 = 5
Total = 20
and so on
and getting the total of it?. the total should be CHANGING when the EditText's value is changing.
I have read this answer. but I can't execute it well on my program.
This is my Layout of it
You need to use a TextWatcher()
instead of using 5 TextWatcher() you can manage it using only a single TextWatcher()
Try this
Using below answer if all your 4 four edittext is not empty then it will calculate the sum of editext value
public class MainActivity extends AppCompatActivity {
EditText edtOne, edtTwo, edtThree, edtFour;
TextView tvResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edtOne = findViewById(R.id.edtOne);
edtTwo = findViewById(R.id.edtTwo);
edtThree = findViewById(R.id.edtThree);
edtFour = findViewById(R.id.edtFour);
tvResult = findViewById(R.id.tvResult);
edtOne.addTextChangedListener(textWatcher);
edtTwo.addTextChangedListener(textWatcher);
edtThree.addTextChangedListener(textWatcher);
edtFour.addTextChangedListener(textWatcher);
}
TextWatcher textWatcher = 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 (!TextUtils.isEmpty(edtOne.getText().toString().trim())
|| !TextUtils.isEmpty(edtTwo.getText().toString().trim())
|| !TextUtils.isEmpty(edtThree.getText().toString().trim())
|| !TextUtils.isEmpty(edtFour.getText().toString().trim())
) {
int answer = Integer.parseInt(edtOne.getText().toString().trim()) +
Integer.parseInt(edtTwo.getText().toString().trim()) +
Integer.parseInt(edtThree.getText().toString().trim()) +
Integer.parseInt(edtFour.getText().toString().trim());
Log.e("RESULT", String.valueOf(answer));
tvResult.setText(String.valueOf(answer));
}else {
tvResult.setText("");
}
}
#Override
public void afterTextChanged(Editable editable) {
}
};
}
UPDATE
if you want to calculate value of all editext evenif your editext is empty than try below TextWatcher()
TextWatcher textWatcher = 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 (!TextUtils.isEmpty(edtOne.getText().toString().trim())
|| !TextUtils.isEmpty(edtTwo.getText().toString().trim())
|| !TextUtils.isEmpty(edtThree.getText().toString().trim())
|| !TextUtils.isEmpty(edtFour.getText().toString().trim())
) {
int firtValue = TextUtils.isEmpty(edtOne.getText().toString().trim()) ? 0 : Integer.parseInt(edtOne.getText().toString().trim());
int secondValue = TextUtils.isEmpty(edtTwo.getText().toString().trim()) ? 0 : Integer.parseInt(edtTwo.getText().toString().trim());
int thirdValue = TextUtils.isEmpty(edtThree.getText().toString().trim()) ? 0 : Integer.parseInt(edtThree.getText().toString().trim());
int forthValue = TextUtils.isEmpty(edtFour.getText().toString().trim()) ? 0 : Integer.parseInt(edtFour.getText().toString().trim());
int answer = firtValue + secondValue + thirdValue + forthValue;
Log.e("RESULT", String.valueOf(answer));
tvResult.setText(String.valueOf(answer));
}else {
tvResult.setText("");
}
}
#Override
public void afterTextChanged(Editable editable) {
}
};
I'm going to tell you how to do it, but I won't post the solution as a total code.
First of all, define integers that is the amount of your edit text count. If there is 4 edit texts, define 4 integers with like int first = 0, second = 0, third = 0, fourth = 0;
Then, add separate text watchers to your edit texts, and on your afterTextChanged methods, get the integer value from the string by using Integer.parseInt(Editable s.getText.toString()) and make sure the input is convertable, otherwise you will get a NumberFormatException. Then, assign this value to the related edit text, for example on your first edit text use first = Integer.parse(s.getText().toString()).
Create a function that uses these variables to display on a textview. For instance:
private void showResult() {
textView.setText(String.valueOf(first + second + third + fourth));
}
Then, at every afterTextChanged methods call this function to display the total amount.

Can I use The same TextWatcher on different EditText widgets

I have a form. I want to display a calculation in "live time" when the user enters different values into some int fields. I made my Activity implement the TextWatcher interface and set a listener on 3 different EditText fields but it appears the Textwatcher only detects the first EditText declared in the Activity's code.
You can see from the code below, I'm trying to grabe a few fields, convert them to ints and display the output in an EditText field at the bottom of the form. Where am I going wrong? Do I need to implement a textWatcher individually on all of the EditText fields involved? That would be a rather verbose solution making my code a lot longer than I would like
public class NewStageFormActivity extends AppCompatActivity implements TextWatcher{
Context mContext;
EditText mStageName, mPaperTargets, mHitsPerTarget, mSteelTargets, mSteelNPMs, mOutput;
Spinner mScoringType, mStrings;
CheckBox mNoShoots, mNPMs;
Button mSaveButton;
Match mGlobalMatch;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stage_form);
mContext = this;
mGlobalMatch = GlobalMatch.getMatch();
mStageName = (EditText)findViewById(R.id.stage_name_et);
mPaperTargets = (EditText)findViewById(R.id.paper_targets_et);
mHitsPerTarget = (EditText)findViewById(R.id.hits_per_target_et);
mSteelTargets = (EditText)findViewById(R.id.steel_targets_et);
mSteelNPMs = (EditText)findViewById(R.id.steel_npm_et);
mScoringType = (Spinner)findViewById(R.id.scoring_type_spinner);
mStrings = (Spinner)findViewById(R.id.strings_spinner);
mNoShoots = (CheckBox)findViewById(R.id.no_shoots_cb);
mNPMs = (CheckBox)findViewById(R.id.npm_cb);
mSaveButton = (Button)findViewById(R.id.save_button);
mOutput = (EditText)findViewById(R.id.output_et);
// paper * hitsPer + steel
mPaperTargets.addTextChangedListener(this);
mSteelTargets.addTextChangedListener(this);
mSteelTargets.addTextChangedListener(this);
mSaveButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mStageName.getText().toString().equals("") || mPaperTargets.getText().toString().equals("") ||
mHitsPerTarget.getText().toString().equals("") || mSteelTargets.getText().toString().equals("") ||
mSteelNPMs.getText().toString().equals("")){
Toast.makeText(mContext, "You must fill in all form fields", Toast.LENGTH_SHORT).show();
} else {
String name = mStageName.getText().toString();
String type = mScoringType.getSelectedItem().toString();
int strings = Integer.valueOf(mStrings.getSelectedItem().toString());
int paperTargets = Integer.valueOf(mPaperTargets.getText().toString());
int hitsPerTarget = Integer.valueOf(mHitsPerTarget.getText().toString());
boolean noShoots;
boolean npms;
if(mNoShoots.isChecked()){
noShoots = true;
} else {
noShoots = false;
}
if(mNPMs.isChecked()){
npms = true;
} else {
npms = false;
}
int steelTargets = Integer.valueOf(mSteelTargets.getText().toString());
int steelNPMs = Integer.valueOf(mSteelNPMs.getText().toString());
MatchStage matchStage = new MatchStage(name, type, strings, paperTargets, hitsPerTarget,
noShoots, npms, steelTargets, steelNPMs);
mGlobalMatch.getStages().add(matchStage);
String jsonString = new Gson().toJson(mGlobalMatch);
MatchHelper.updateFile(mContext, MatchHelper.createFileName(mGlobalMatch.getMatchId()),
jsonString);
Intent intent = new Intent(mContext, StagesListActivity.class);
startActivity(intent);
}
}
});
}
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
int paper = Integer.valueOf(mPaperTargets.getText().toString());
int hitsPer = Integer.valueOf(mHitsPerTarget.getText().toString());
int steel = Integer.valueOf(mSteelTargets.getText().toString());
int minRound = (paper * hitsPer) + steel;
int points = minRound * 5;
mOutput.setText("Minimum rounds: " + (minRound) + "\t\t Points: " + points);
}
#Override
public void afterTextChanged(Editable editable) {
}
}
In my experience I've had issues with using the same TextWatcher on multiple EditText. You could get around this by creating a method that produces a new instance of TextWatcher for each EditText so your code isn't all verbose. Try something like this:
Get rid of implements TextWatcher for your Activity and it's associated methods. Implement a method createTextWatcher():
private TextWatcher createTextWatcher() {
return new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// Copy your original code
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// Copy your original code
}
#Override
public void afterTextChanged(Editable editable) {
// Copy your original code
}
};
}
Now to use it like this:
mPaperTargets.addTextChangedListener(createTextWatcher());
mSteelTargets.addTextChangedListener(createTextWatcher());
The most up-voted answer on #Natan Felipe's link also demonstrates using one instance of TextWatcher per EditText.

How to set different colors for each characters written in edittext in Android?

I am trying make characters written in edittext colored with a different color.
For example, I want to have 'a' in red all the time when it is written in edittext, while the others stay in black. Is it possible at least?
I found some answers regarding color-setting in edittext as below, however it is all about color-setting by the range of start index and end index.
** example **
final String text = "for example";
Spannable modifiedText = new SpannableString(text);
modifiedText.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.red)), 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(modifiedText);
Yes it's possible, but I don't know if is too expensive in terms of performance.
You can use a TextWatcher to color you last char inserted base on your Map of char-color.
public class MainActivity extends AppCompatActivity {
private SpannableStringBuilder mSpannableStringBuilder;
private EditText mEditText;
private static final Map<String, Integer> COLORS_MAP = new HashMap<>();
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// here you can populate your map with colors
COLORS_MAP.put("a", Color.RED);
COLORS_MAP.put("b", Color.GREEN);
COLORS_MAP.put("c", Color.BLUE);
COLORS_MAP.put("d", Color.MAGENTA);
mSpannableStringBuilder = new SpannableStringBuilder();
mEditText = (EditText) findViewById(R.id.editText);
mEditText.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 (s.length() > 0) {
// unregister and register the listener to avoid infinite loop
mEditText.removeTextChangedListener(this);
int start = s.length() - 1;
String lastChar = s.toString().substring(start);
SpannableString lastSpannableChar = new SpannableString(lastChar);
// pick the color based on the last char
int color = pickColorByChar(lastChar);
// Span to set char color
ForegroundColorSpan fcs = new ForegroundColorSpan(color);
// Set the text color for the last character
lastSpannableChar.setSpan(fcs, 0, 1, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
// append the last char to the string builder so you can keep the previous span
mSpannableStringBuilder.append(lastSpannableChar);
mEditText.setText(mSpannableStringBuilder);
mEditText.setSelection(mEditText.getText().length()); //this is to move the cursor position
mEditText.addTextChangedListener(this);
}
}
});
}
public int pickColorByChar(String aChar){
return COLORS_MAP.get(aChar);
}
}
This is the result
One way would be to use Html.fromHtml(String) and set the font colors through that using a Map to your predefined colors. e.g.
private static final String FONT_REPLACEMENT = "<font color='%1$s'>%2$s</font>";
private static final String DEFAULT_COLOR = "#FAFAFA";
public Spanned convertToHtml(String text, Map<String, String> colorSets){
String altered = "<![CDATA[";
for(int i = 0; i < text.length(); i++) {
String value = String.valueOf(text.charAt(i));
String color = colorSets.get(value.toLowerCase(Locale.US));
if(color == null)
color = DEFAULT_COLOR;
altered += String.format(FONT_REPLACEMENT, color, value);
}
return Html.fromHtml(altered + "]]>");
}
And then to use it, you could do something like:
Map<String, String> colors = new HashMap<String, String();
colors.put("a", "#FF0000");
colors.put("b", "#00FF00");
colors.put("c", "#0000FF");
....
textView.setText(convertToHtml("for example", colors));

Categories