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);
I am working on an android app where I am changing the some of EditText's Value programmatically on manually change of EditText's Value.
When user change the quantity I am changing the total price & sale price value.
When user change the sale price I am changing the discount value.
When user change the discount I am changing the sale price value.
I have added a addTextChangedListener() on every EditText. But before that I have created TextWatcher object for each EditText's globally.
private TextWatcher quantityWatcher;
private TextWatcher priceWatcher;
private TextWatcher discountWatcher;
And define it onBindViewHolder() method, so whenever I want to remove or add a TextChangedListener() on it, I can do it easily.
Before changing the any EditText's values programmatically I am removing the addTextChangedListener() on every TextWatcher's objects by using removeTextChangedListener() to avoid calling the function by itself. After changing the value and registering back the listener on it.
For Quantity EditText
quantityWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: quantityWatcher Event Listener Called");
quantityEvent(holder);
}
};
For Discount EditText.
priceWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: priceWatcher Event Listener Called");
priceEvent(holder);
}
};
For Sale Price EditText
discountWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: discountWatcher Event Listener Called");
discountInputEvent(holder);
}
};
The method which I am calling on change of EditText's values.
private void priceEvent(ViewHolder holder) {
Log.d("SocialCodia", "PriceEvent Method Called");
unregisterTextWatcher(holder);
int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
String sellPriceString = holder.inputSalePrice.getText().toString().trim();
if (sellPriceString.trim().length()>0)
{
int sellPrice = Integer.parseInt(holder.inputSalePrice.getText().toString().trim());
int discount = percentage(sellPrice, totalPrice);
holder.inputSaleDiscount.setText(String.valueOf(discount));
}
else
{
holder.inputSaleDiscount.setText(String.valueOf(100));
}
registerTextWatchers(holder);
}
private void quantityEvent(ViewHolder holder)
{
Log.d("SocialCodia", "quantityEvent Method Called");
unregisterTextWatcher(holder);
String quan = holder.inputSaleQuantity.getText().toString().trim();
String per = holder.inputSaleDiscount.getText().toString().trim();
int quantity;
int percentage;
if (quan == null || quan.length()<1 || quan.isEmpty())
quantity = 1;
else
quantity = Integer.parseInt(quan);
if (per==null || per.length()<1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = Integer.parseInt(holder.tvProductPrice.getText().toString());
int finalPrice = price*quantity;
holder.inputTotalPrice.setText(String.valueOf(finalPrice));
int salePrice = percentageDec(finalPrice,percentage);
holder.inputSalePrice.setText(String.valueOf(salePrice));
registerTextWatchers(holder);
}
private void discountInputEvent(ViewHolder holder) {
Log.d("SocialCodia", "discountInputEvent Method Called");
unregisterTextWatcher(holder);
int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
String per = holder.inputSaleDiscount.getText().toString().trim();
int percentage;
if (per==null || per.length()<1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = percentageDec(totalPrice, percentage);
holder.inputSalePrice.setText(String.valueOf(price));
registerTextWatchers(holder);
}
private int percentage(int partialValue, int totalValue) {
Log.d("SocialCodia", "percentage Method Called");
Double partial = (double) partialValue;
Double total = (double) totalValue;
Double per = (100 * partial) / total;
Double p = 100 - per;
return p.intValue();
}
private int percentageDec(int totalValue, int per) {
Log.d("SocialCodia", "percentageDec Method Called");
if (per == 0 || String.valueOf(per).length() < 0)
return totalValue;
else {
Double total = (double) totalValue;
Double perc = (double) per;
Double price = (total - ((perc / 100) * total));
Integer p = price.intValue();
return p;
}
}
Every conditions, logic, or method are working fine. But when I am inserting more than one views in recyclerview. Changing of any rows EditText's value except the current inserted views calling the listener itself again and again.
I have tried to figure out the exact issue but unable to do it.
My Adapter Class AdapterSaleEditable.java
public class AdapterSaleEditable extends RecyclerView.Adapter<AdapterSaleEditable.ViewHolder> {
private Context context;
private List<ModelSale> modelSaleList;
private String token;
private SharedPrefHandler sp;
private ModelUser user;
private boolean discountFlag = false;
private boolean priceEvenFlag = false;
private TextWatcher quantityWatcher;
private TextWatcher priceWatcher;
private TextWatcher discountWatcher;
public AdapterSaleEditable(Context context, List<ModelSale> modelSales) {
this.context = context;
this.modelSaleList = modelSales;
sp = SharedPrefHandler.getInstance(context);
user = sp.getUser();
token = user.getToken();
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.row_sale_editable, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ModelSale sale = modelSaleList.get(position);
int productId = sale.getProductId();
int saleId = sale.getSaleId();
String productCategory = sale.getProductCategory();
String productName = sale.getProductName();
String productSize = sale.getProductSize();
String productBrand = sale.getProductBrand();
int productPrice = sale.getProductPrice();
int productQuantity = sale.getProductQuantity();
String productManufacture = sale.getProductManufacture();
String productExpire = sale.getProductExpire();
String createdAt = sale.getCreatedAt();
holder.tvProductName.setText(productName);
holder.tvProductSize.setText("(" + productSize + ")");
holder.tvProductCategory.setText(productCategory);
holder.tvProductPrice.setText(String.valueOf(productPrice));
holder.inputTotalPrice.setText(String.valueOf(productPrice));
holder.inputSaleQuantity.setText(String.valueOf(1));
holder.inputSalePrice.setText(String.valueOf(productPrice));
holder.inputSaleDiscount.setText(String.valueOf(0));
holder.tvProductBrand.setText(productBrand);
holder.tvProductManufacture.setText(productManufacture);
holder.tvProductExpire.setText(productExpire);
holder.tvCount.setText(String.valueOf(position + 1));
holder.cvSell.setOnLongClickListener(view -> {
showDeleteAlert(holder, sale, position);
return true;
});
quantityWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: quantityWatcher Event Listener Called");
quantityEvent(holder);
}
};
priceWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: priceWatcher Event Listener Called");
priceEvent(holder);
}
};
discountWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: discountWatcher Event Listener Called");
discountInputEvent(holder);
}
};
registerTextWatchers(holder);
//End on create method
}
private void registerTextWatchers(ViewHolder holder) {
Log.d("SocialCodia", "Registring Listener");
holder.inputSaleQuantity.addTextChangedListener(quantityWatcher);
holder.inputSalePrice.addTextChangedListener(priceWatcher);
holder.inputSaleDiscount.addTextChangedListener(discountWatcher);
}
private void unregisterTextWatcher(ViewHolder holder)
{
Log.d("SocialCodia", "UnRegistring Listener");
holder.inputSaleQuantity.removeTextChangedListener(quantityWatcher);
holder.inputSalePrice.removeTextChangedListener(priceWatcher);
holder.inputSaleDiscount.removeTextChangedListener(discountWatcher);
}
private void priceEvent(ViewHolder holder) {
Log.d("SocialCodia", "PriceEvent Method Called");
unregisterTextWatcher(holder);
int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
String sellPriceString = holder.inputSalePrice.getText().toString().trim();
if (sellPriceString.trim().length()>0)
{
int sellPrice = Integer.parseInt(holder.inputSalePrice.getText().toString().trim());
int discount = percentage(sellPrice, totalPrice);
holder.inputSaleDiscount.setText(String.valueOf(discount));
}
else
{
holder.inputSaleDiscount.setText(String.valueOf(100));
}
registerTextWatchers(holder);
}
private void quantityEvent(ViewHolder holder)
{
Log.d("SocialCodia", "quantityEvent Method Called");
unregisterTextWatcher(holder);
String quan = holder.inputSaleQuantity.getText().toString().trim();
String per = holder.inputSaleDiscount.getText().toString().trim();
int quantity;
int percentage;
if (quan == null || quan.length()<1 || quan.isEmpty())
quantity = 1;
else
quantity = Integer.parseInt(quan);
if (per==null || per.length()<1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = Integer.parseInt(holder.tvProductPrice.getText().toString());
int finalPrice = price*quantity;
holder.inputTotalPrice.setText(String.valueOf(finalPrice));
int salePrice = percentageDec(finalPrice,percentage);
holder.inputSalePrice.setText(String.valueOf(salePrice));
registerTextWatchers(holder);
}
private void discountInputEvent(ViewHolder holder) {
Log.d("SocialCodia", "discountInputEvent Method Called");
unregisterTextWatcher(holder);
int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
String per = holder.inputSaleDiscount.getText().toString().trim();
int percentage;
if (per==null || per.length()<1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = percentageDec(totalPrice, percentage);
holder.inputSalePrice.setText(String.valueOf(price));
registerTextWatchers(holder);
}
private int percentage(int partialValue, int totalValue) {
Log.d("SocialCodia", "percentage Method Called");
Double partial = (double) partialValue;
Double total = (double) totalValue;
Double per = (100 * partial) / total;
Double p = 100 - per;
return p.intValue();
}
private int percentageDec(int totalValue, int per) {
Log.d("SocialCodia", "percentageDec Method Called");
if (per == 0 || String.valueOf(per).length() < 0)
return totalValue;
else {
Double total = (double) totalValue;
Double perc = (double) per;
Double price = (total - ((perc / 100) * total));
Integer p = price.intValue();
return p;
}
}
private void showDeleteAlert(ViewHolder holder, ModelSale sale, int position) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Are you sure want to delete?");
builder.setMessage("You are going to delete " + sale.getProductName() + ". The Sale Quantity of this product was " + sale.getSaleQuantity() + " and the total price was " + sale.getSalePrice());
builder.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
deleteSoldProduct(sale.getSaleId(), position);
}
});
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
Toast.makeText(context, "Deletion Canceled", Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
private void deleteSoldProduct(int sellId, int position) {
Call<ResponseDefault> call = ApiClient.getInstance().getApi().deleteSoldProduct(sellId, token);
call.enqueue(new Callback<ResponseDefault>() {
#Override
public void onResponse(Call<ResponseDefault> call, Response<ResponseDefault> response) {
if (response.isSuccessful()) {
ResponseDefault responseDefault = response.body();
if (!responseDefault.isError()) {
TastyToast.makeText(context, responseDefault.getMessage(), Toast.LENGTH_SHORT, TastyToast.SUCCESS);
Helper.playSuccess();
Helper.playVibrate();
modelSaleList.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, modelSaleList.size());
} else
TastyToast.makeText(context, responseDefault.getMessage(), Toast.LENGTH_SHORT, TastyToast.ERROR);
} else
Toast.makeText(context, "Request Isn't Success", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ResponseDefault> call, Throwable t) {
t.printStackTrace();
}
});
}
public void updateList(List<ModelSale> list) {
modelSaleList = list;
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return modelSaleList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView tvProductName, tvProductSize, tvProductCategory, tvSaleTime, tvProductPrice, tvProductBrand, tvProductManufacture, tvProductExpire, tvCount;
private EditText inputSaleQuantity, inputSaleDiscount, inputSalePrice, inputTotalPrice;
private CardView cvSell;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvProductName = itemView.findViewById(R.id.tvProductName);
tvProductSize = itemView.findViewById(R.id.tvProductSize);
tvProductCategory = itemView.findViewById(R.id.tvProductCategory);
tvSaleTime = itemView.findViewById(R.id.tvSaleTime);
tvProductPrice = itemView.findViewById(R.id.tvProductPrice);
inputSaleQuantity = itemView.findViewById(R.id.inputSaleQuantity);
inputSaleDiscount = itemView.findViewById(R.id.inputSaleDiscount);
inputSalePrice = itemView.findViewById(R.id.inputSalePrice);
tvProductBrand = itemView.findViewById(R.id.tvProductBrand);
tvProductManufacture = itemView.findViewById(R.id.tvProductManufacture);
tvProductExpire = itemView.findViewById(R.id.tvProductExpire);
inputTotalPrice = itemView.findViewById(R.id.inputTotalPrice);
tvCount = itemView.findViewById(R.id.tvCount);
cvSell = itemView.findViewById(R.id.cvSell);
}
}
}
My Fragment. From Where I am setting the recyclerview. SellProductFragment.java
public class SellProductActivity extends AppCompatActivity {
private ImageView ivCloseDialog;
private RecyclerView recyclerView;
private EditText inputSearchProduct;
private static List<ModelProduct> modelProductList;
private AdapterProductSale adapterProductSale;
private int productId;
private ActionBar actionBar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sell_product);
init();
actionBar = getSupportActionBar();
actionBar.setTitle("Sell Product");
setRecyclerView();
inputSearchProduct.addTextChangedListener(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) {
filter(editable.toString());
}
});
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_close,menu);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
int id = item.getItemId();
if (id==R.id.miClose)
{
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
private void filter(String text)
{
List<ModelProduct> p = new ArrayList<>();
for(ModelProduct sale : modelProductList)
{
if (sale.getProductName().toLowerCase().trim().contains(text.toLowerCase()))
{
p.add(sale);
}
}
adapterProductSale.updateList(p);
}
private void setRecyclerView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
modelProductList = DbHandler.getModelProductList();
adapterProductSale = new AdapterProductSale(SellProductActivity.this, modelProductList);
recyclerView.setAdapter(adapterProductSale);
}
private void init() {
recyclerView = findViewById(R.id.rvProducts);
inputSearchProduct = findViewById(R.id.inputSearchProduct);
modelProductList = new ArrayList<>();
}
}
How can I solve the issue.
-Thanks for any help!
But when I am inserting more than one views in recyclerview. Changing of any rows EditText's value except the current inserted views calling the listener itself again and again.
Well, the main issue of listener replication over and over again, that theses listeners exist in onBindViewHolder() as this method gets called every time a RecyclerView row is going to be displayed/recycled/changed/inserted on the screen; and that apparently happened whenever you added new items.
So, the possible way is to register these listeners somewhere else that going to be called once, or whenever you want to; i.e. not every time the rows are recycled.
You can do that in the ViewHolder constructor to the EditText's themselves.
Challenge: how can we know which EditText that the user modified? .. As if some EditText is modified and you recycled the views (i.e. scrolled up/down the list), you will see the value is messed up in multiple rows.
This can be solved by:
Tracking the EditText values in your model class ModelSale.. Not
sure if you already did that or not.. anyways this class should have
fields, getters, & setters correspond to the EditTexts fields which
we have (quantity, discount, & price). And these fields should
be set in the onBindViewHoder() to get the saved values whenever
the rows are recycled.
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ModelSale sale = modelSaleList.get(position);
// ...... rest of your code
holder.unregisterTextWatcher();
holder.inputSaleQuantity.setText(sale.getQuantatiy());
holder.inputSaleDiscount.setText(sale.getDiscount());
holder.inputSalePrice.setText(sale.getPrice());
holder.registerTextWatchers();
//End on create method
}
Getting the current item in the ViewHolder using getAdapterPostion()
And this approach requires to move all the watchers, fields, & methods that are related to EditText watchers from the RecyclerViewAdapter to the ViewHolder
And every time before changing these EditTexts fields, you need to unregsiter the text Watchers.
And here's the adapter only with those modifications in order to be compact.
public class AdapterSaleEditable extends RecyclerView.Adapter<AdapterSaleEditable.ViewHolder> {
// ... your code
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ModelSale sale = modelSaleList.get(position);
// ...... rest of your code
holder.unregisterTextWatcher();
holder.inputSaleQuantity.setText(sale.getQuantatiy());
holder.inputSaleDiscount.setText(sale.getDiscount());
holder.inputSalePrice.setText(sale.getPrice());
holder.registerTextWatchers();
//End on create method
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView tvProductName, tvProductSize, tvProductCategory, tvSaleTime, tvProductPrice, tvProductBrand, tvProductManufacture, tvProductExpire, tvCount;
private EditText inputSaleQuantity, inputSaleDiscount, inputSalePrice, inputTotalPrice;
private CardView cvSell;
private TextWatcher quantityWatcher;
private TextWatcher priceWatcher;
private TextWatcher discountWatcher;
private void registerTextWatchers() {
Log.d("SocialCodia", "Registring Listener");
inputSaleQuantity.addTextChangedListener(quantityWatcher);
inputSalePrice.addTextChangedListener(priceWatcher);
inputSaleDiscount.addTextChangedListener(discountWatcher);
}
private void unregisterTextWatcher() {
Log.d("SocialCodia", "UnRegistring Listener");
inputSaleQuantity.removeTextChangedListener(quantityWatcher);
inputSalePrice.removeTextChangedListener(priceWatcher);
inputSaleDiscount.removeTextChangedListener(discountWatcher);
}
private void priceEvent() {
Log.d("SocialCodia", "PriceEvent Method Called");
unregisterTextWatcher();
int totalPrice = Integer.parseInt(inputTotalPrice.getText().toString().trim());
String sellPriceString = inputSalePrice.getText().toString().trim();
if (sellPriceString.trim().length() > 0) {
int sellPrice = Integer.parseInt(inputSalePrice.getText().toString().trim());
int discount = percentage(sellPrice, totalPrice);
inputSaleDiscount.setText(String.valueOf(discount));
} else {
inputSaleDiscount.setText(String.valueOf(100));
}
registerTextWatchers();
}
private void quantityEvent() {
Log.d("SocialCodia", "quantityEvent Method Called");
unregisterTextWatcher();
String quan = inputSaleQuantity.getText().toString().trim();
String per = inputSaleDiscount.getText().toString().trim();
int quantity;
int percentage;
if (quan == null || quan.length() < 1 || quan.isEmpty())
quantity = 1;
else
quantity = Integer.parseInt(quan);
if (per == null || per.length() < 1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = Integer.parseInt(tvProductPrice.getText().toString());
int finalPrice = price * quantity;
inputTotalPrice.setText(String.valueOf(finalPrice));
int salePrice = percentageDec(finalPrice, percentage);
inputSalePrice.setText(String.valueOf(salePrice));
registerTextWatchers();
}
private void discountInputEvent() {
Log.d("SocialCodia", "discountInputEvent Method Called");
unregisterTextWatcher();
int totalPrice = Integer.parseInt(inputTotalPrice.getText().toString().trim());
String per = inputSaleDiscount.getText().toString().trim();
int percentage;
if (per == null || per.length() < 1)
percentage = 0;
else
percentage = Integer.parseInt(per);
int price = percentageDec(totalPrice, percentage);
inputSalePrice.setText(String.valueOf(price));
registerTextWatchers();
}
private int percentage(int partialValue, int totalValue) {
Log.d("SocialCodia", "percentage Method Called");
Double partial = (double) partialValue;
Double total = (double) totalValue;
Double per = (100 * partial) / total;
Double p = 100 - per;
return p.intValue();
}
private int percentageDec(int totalValue, int per) {
Log.d("SocialCodia", "percentageDec Method Called");
if (per == 0 || String.valueOf(per).length() < 0)
return totalValue;
else {
Double total = (double) totalValue;
Double perc = (double) per;
Double price = (total - ((perc / 100) * total));
Integer p = price.intValue();
return p;
}
}
public ViewHolder(#NonNull View itemView) {
super(itemView);
// Rest of your code
// Text Watchers
quantityWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: quantityWatcher Event Listener Called");
quantityEvent();
}
};
priceWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: priceWatcher Event Listener Called");
priceEvent();
}
};
discountWatcher = 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) {
Log.d("SocialCodia", "afterTextChanged: discountWatcher Event Listener Called");
discountInputEvent();
}
};
registerTextWatchers();
}
}
}
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.
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.
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.