Search code examples
javaandroidandroid-edittextlistener

Remove addTextChangedListener() When the EditText values changed programmatically not manually


I was working on a website where I was changing the text on change of the text using Javascript.

  1. When user change the quantity I am changing the total price & sale price value.
  2. When user change the sale price I am changing the discount value.
  3. When user change the discount I am changing the sale price value.

enter image description here

Now same thing I want in my android application.

I have added Text Change Event Listener on every EditText.

Like

For Quantity EditText

    holder.inputSaleQuantity.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) {

        }
    });

For Discount EditText.

holder.inputSaleDiscount.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) {
                Log.d("SocialCodia", "afterTextChanged: inputSaleDiscount Event Listener Called");
                int input = 0;
                if (editable.toString().trim().length() > 0) {
                    input = Integer.parseInt(editable.toString().trim());
                }
                    discountInputEvent(holder, input);
            }
        });

For Sale Price EditText.

holder.inputSalePrice.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) {
                priceEvent(holder);
                Log.d("SocialCodia", "afterTextChanged: inputSalePrice Event Listener Called");
            }
        });

POSSIBILITIES WHY EXECUTING METHOD AGAIN AND AGAIN.

When I am changing the any EditText's value like, Changing the Quantities EditText's value, Its calling sale price edit text change listener as well.

Because on change of Quantity value I am changing the sell price value. So when the sell price value change there text change listener executing.

0

Methods which I am calling.

private void priceEvent(ViewHolder holder) {
        int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
        int sellPrice = Integer.parseInt(holder.inputSalePrice.getText().toString().trim());
        int discount = percentage(sellPrice, totalPrice);
        holder.inputSaleDiscount.setText(String.valueOf(discount));
    }

    private void discountInputEvent(ViewHolder holder, int input) {
        int totalPrice = Integer.parseInt(holder.inputTotalPrice.getText().toString().trim());
        int price = percentageDec(totalPrice, input);
        holder.inputSalePrice.setText(String.valueOf(price));
    }

    private int percentage(int partialValue, int totalValue) {
        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) {
        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;
        }
    }

CLEAR QUESTION IN SHORT :

I only want to use addTextChangeEventListener() When the value of EditText Change Manually. But when I am changing the value using script I don't want to use the addTextChangeEventListner().

How can I achieve this. or how can I solve this problem.

-Thanks


Solution

  • Short Answer:

    The TextWatcher's need to be defined non-anonymously (i.e. with variables), so that you can register them with addTextChangedListener(myWatcher) and whenever you want to cease them, you can un-register them with removeTextChangedListener(myWatcher) and then re-register them back again with addTextChangedListener(myWatcher) when you're done with script modification.

    Long Answer

    Building initial TextWatcher variables & register them to EditTexts

    // Build variables for text watchers
    
    TextWatcher 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) {
    
        }
    };
    
    TextWatcher salePriceWatcher = 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) {
    
        }
    };
    
    TextWatcher 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) {
    
        }
    };
    

    Initially register all the text watchers.

    registerTextWatchers();
    
    private void registerTextWatchers() {
        holder.inputSaleQuantity.addTextChangedListener(quantityWatcher);
        holder.inputSalePrice.addTextChangedListener(salePriceWatcher);
        holder.inputSaleDiscount.addTextChangedListener(discountWatcher);   
    }
    

    Unregister the watchers whenever you change the EditText programmatically and register them again when you're done

    private void unregisterTextWatchers() {
        holder.inputSaleQuantity.removeTextChangedListener(quantityWatcher);
        holder.inputSalePrice.removeTextChangedListener(salePriceWatcher);
        holder.inputSaleDiscount.removeTextChangedListener(discountWatcher);    
    }
    
    private void priceEvent(ViewHolder holder) {
        //...
        
        unregisterTextWatchers();
        holder.inputSaleDiscount.setText(String.valueOf(discount));
        registerTextWatchers();
    }
    
    private void discountInputEvent(ViewHolder holder, int input) {
        //...
        
        unregisterTextWatchers();
        holder.inputSalePrice.setText(String.valueOf(price));
        registerTextWatchers();
    }
    

    Repeat the same whenever you change the EditText values programmatically