两个TextWatchers创建一个无限循环

时间:2017-05-12 23:04:21

标签: android textwatcher

我的Android应用程序中有3个EditText字段,我正在尝试彼此通信。它们是订单总额,收到的金额和小费。用户在第一个EditText中输入订单的价格。另外两个EditTexts是我想根据每个EditTexts的值修改的。如果用户在订单总数中输入20.00,在收到的金额中输入25.00,我希望提示显示5.00。同样,如果他们在订单总数中输入20.00,在提示中输入5.00,我希望收到的金额显示为25.00。我的所有计算都是正确的,只要另一个被注释掉,我的TextWatchers中的每一个都可以工作,但是对于它们两者,它只会创建一个无限循环。有没有一个很好的方法来做到这一点,或者有人可以指出我正确的方向一些有用的链接?我似乎找不到任何可行的工作。

我的代码如下:

eTotalCost = (EditText) findViewById(R.id.orderTotal);
eAmountReceived = (EditText) findViewById(R.id.amountReceived);
eTip = (EditText) findViewById(R.id.tip);
eMileage = (EditText) findViewById(R.id.mileage);
eGrandTotal = (EditText) findViewById(R.id.grandTotal);

eAmountReceived.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)
    {
        eAmountReceived = (EditText) findViewById(R.id.amountReceived);
        eTotalCost = (EditText) findViewById(R.id.orderTotal);
        eTip = (EditText) findViewById(R.id.tip);
        eMileage = (EditText) findViewById(R.id.mileage);
        eGrandTotal = (EditText) findViewById(R.id.grandTotal);

        sAmountReceived = eAmountReceived.getText().toString();
        sTotalCost = eTotalCost.getText().toString();
        sMileage = eMileage.getText().toString();
        sTip = eTip.getText().toString();

        try
        {
            dAmountReceived = Double.parseDouble(sAmountReceived);
            dTotalCost = Double.parseDouble(sTotalCost);

            dSubtract = dAmountReceived - dTotalCost;
            dMileage = Double.parseDouble(sMileage);
            dGrandTotal = dSubtract + dMileage;
        } catch(NumberFormatException e){}

        sTip = String.valueOf(dSubtract);

        DecimalFormat df = new DecimalFormat("0.00");
        sTip = df.format(dSubtract);

        eTip.setText(sTip);

        sGrandTotal = String.valueOf(dGrandTotal);
        sGrandTotal = df.format(dGrandTotal);
        eGrandTotal.setText(sGrandTotal);
    }
});


eTip.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) {
        eAmountReceived = (EditText) findViewById(R.id.amountReceived);
        eTotalCost = (EditText) findViewById(R.id.orderTotal);
        eTip = (EditText) findViewById(R.id.tip);
        eMileage = (EditText) findViewById(R.id.mileage);
        eGrandTotal = (EditText) findViewById(R.id.grandTotal);

        sAmountReceived = eAmountReceived.getText().toString();
        sTotalCost = eTotalCost.getText().toString();
        sMileage = eMileage.getText().toString();
        sTip = eTip.getText().toString();

        try 
        {
            dTip = Double.parseDouble(sTip);
            dTotalCost = Double.parseDouble(sTotalCost);

            dAdd = dTotalCost + dTip;
            dMileage = Double.parseDouble(sMileage);
            dGrandTotal = dTip + dMileage;
        } catch (NumberFormatException e) {}

        sAmountReceived = String.valueOf(dAdd);

        DecimalFormat df = new DecimalFormat("0.00");
        sAmountReceived = df.format(dAdd);

        eAmountReceived.setText(sAmountReceived);

        sGrandTotal = String.valueOf(dGrandTotal);
        sGrandTotal = df.format(dGrandTotal);
        eGrandTotal.setText(sGrandTotal);
    }
});

3 个答案:

答案 0 :(得分:2)

您正在使用afterTextChanged回调

循环setText方法

发生了什么:

您有2个textWatchers:一个用于eTip,另一个用于eAmountReceived

当您在其中任何一个字段上调用setText()时,它将开始循环播放,因为setText将触发afterTextChanged,并且在您的两个文本观察者中,您正在调用setText()的相反字段,再次,将触发afterTextChanged

为了避免这种情况,引入一些布尔标志,表示已经为各个edittext设置了值,或者只有当新值与之前设置的值不同时才调用setText

答案 1 :(得分:1)

首先删除afterTextChanged中的findviewbyid代码。您无需在每次使用中声明它们。只能在onCreate中使用。

对于您的问题,最简单的解决方案是将TextWatchers保存在类中声明的变量中。然后在每次调用setText()之前,为所有textWatchers调用removeTextChangeListener,并在setText()之后重新添加textWatchers。

编辑:不删除并重新添加所有setText()调用。只在条件循环中执行。

答案 2 :(得分:0)

在尝试创建货币转换器应用时,我遇到了同样的问题。 (editText 1中的更改​​值应更改editText 2中的值,反之亦然)。

我解决这个问题的方法是创建两个文本观察者。

private TextWatcher TextWatcherClass = new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before,
                              int count) {
        editText2.removeTextChangedListener(TextWatcherClass2);

        }

    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
                                  int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {

        editText2.addTextChangedListener(TextWatcherClass2);
    }

};

private TextWatcher TextWatcherClass2 = new TextWatcher() {

    @Override
    public void onTextChanged(CharSequence s, int start, int before,
                              int count) {
        editText1.removeTextChangedListener(TextWatcherClass);
        }
    }

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count,
                                  int after) {
    }

    @Override
    public void afterTextChanged(Editable s) {

        editText1.addTextChangedListener(TextWatcherClass);
    }

};

希望这有帮助。