2017-05-12 3 views
1

Ich habe 3 EditText Felder in meiner Android App, die ich miteinander kommunizieren möchte. Sie sind Bestellsumme, Betrag erhalten und Trinkgeld. Der Benutzer gibt den Preis der Bestellung im ersten EditText ein. Die anderen beiden EditTexts sind diejenigen, die ich basierend auf dem Wert von jedem ändern möchte. Wenn der Benutzer 20,00 in die Bestellsumme und 25,00 in den erhaltenen Betrag eingibt, möchte ich, dass der Tipp 5,00 anzeigt. Ebenso, wenn sie 20.00 in der Bestellsumme eingeben, und 5.00 im Trinkgeld, würde ich gerne erhalten, um 25.00 anzuzeigen. Ich habe alle Berechnungen korrekt, und jeder meiner TextWatchers funktioniert, solange der andere auskommentiert ist, aber mit beiden schafft es nur eine Endlosschleife. Gibt es einen guten Weg, dies zu tun, oder kann mir jemand bitte in die richtige Richtung zu einigen hilfreichen Links zeigen? Ich kann anscheinend keine Arbeit für das finden, was ich versuche zu tun.Zwei TextWatchers erstellen eine Endlosschleife

Mein Code ist wie folgt:

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); 
    } 
}); 

Antwort

2

Du Looping setText Methoden aus withing afterTextChanged Rückruf

Was ist los:

Sie haben 2 textWatchers: eine für eTip und eine für eAmountReceived

Wenn Sie setText() auf einem dieser Felder aufrufen, wird es in Schleife gestartet, da setText afterTextChanged auslösen und in beiden Ihren Text-Beobachter Sie setText() für entgegengesetzte Feld rufen, die wiederum löst afterTextChanged

Um dies zu vermeiden, stellen einige boolean Flags, die für sich Wert bereits eingestellt jeweiligen EditText anzeigt oder rufen Sie setText nur dann auf, wenn sich der neue Wert von dem bereits eingestellten Wert unterscheidet

+0

Ich bin noch nicht vertraut mit Booleschen Flags. Ich habe eine isSet() -Funktion gemacht und dachte, ich wäre auf dem richtigen Weg, aber ich denke nicht. Wie auch immer, ich habe es zum Laufen gebracht, indem ich (getCurrentFocus() == myEditText) in jedem afterTextChanged ausgeführt habe. – deadAhead

1

Löschen Sie zunächst die findviewbyid-Codes in afterTextChanged. Sie müssen sie nicht bei jeder Verwendung deklarieren. Nur in onCreate verwenden.

Die einfachste Lösung für Ihre Frage halten Sie Ihre TextWatchers in Variablen in der Klasse deklariert. Rufen Sie dann vor jedem Aufruf von setText() remoteTextChangeListener für alle textWatchers auf und fügen Sie nach setText() textWatchers hinzu.

Edit: nicht entfernen und neu hinzufügen in allen setText() -Aufruf. Mach es nur im Zustand macht Schleife.

0

Ich hatte genau dieses Problem beim Versuch, eine Währungsrechner-App zu erstellen. (Ändere den Wert in editText 1 sollte den Wert in editText 2 ändern und umgekehrt).

Die Art, wie ich es geschafft habe, war, zwei Textbeobachter zu erstellen.

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); 
    } 

}; 

Hoffe, das hilft.