Android-Datenbindung mit dem logischen Operator "&&"

131

Ich versuche, den Operator und "&&" in XML mithilfe der Android-Datenbindung zu verwenden.

android:visibility="@{(bean.currentSpaceId == bean.selectedSpaceId **&&** bean.currentSpaceId > 0)? View.VISIBLE: View.GONE}"

aber ich habe den Kompilierungsfehler bekommen:

Fehler: Ausführung für Task ': app: dataBindingProcessLayoutsDevDebug' fehlgeschlagen. org.xml.sax.SAXParseException; systemId: file: /Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; lineNumber: 106; columnNumber: 89; Der Entitätsname muss unmittelbar auf das '&' in der Entitätsreferenz folgen.

und rote Markierung Fehler in Android Studio "unescaped & oder nicht terminierte Zeichen".

Wie soll ich das beheben?

Bearbeiten: fand die Antwort, diese Zeichen müssen maskiert werden:

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'
David Cheung
quelle
Ich habe festgestellt, dass ich ">" und "<" in Layout-XML-Dateien verwenden kann.
Hong

Antworten:

233

&&sollte als gerendert werden &amp;&amp;.

Der offizielle Leitfaden zur Datenbindung enthält Beispiele für Vergleichsoperatoren, bei denen diese XML-Entitäten beispielsweise verwendet werden

android:visibility="@{age &lt; 13 ? View.GONE : View.VISIBLE}"

Bearbeiten

Die Beispielausdrücke, die ich in der Antwort erwähnt habe, sind aus der englischen Version der Dokumente verschwunden, da diese Antwort geschrieben wurde. Sie überleben in einigen veralteten nicht-englischen Versionen der Dokumente wie der spanischen Version.

In beiden Fällen ist die ursprüngliche Antwort weiterhin gültig, da die Verwendung von XML-Entitäten in XML in XML Standard ist und nichts mit Android selbst zu tun hat.

Leo unterstützt Monica Cellio
quelle
12
Verwenden Sie keine Domänenlogik zum Binden von Ausdrücken, Sie haben hierfür Preseter / Controller.
Artkoenig
2
@ ArtjomKönig was ist, wenn Sie einige Steuerelemente in der Benutzeroberfläche ausblenden / anzeigen müssen? Ich benutze Datenbindungsbibliothek, um NICHT UI-Code zu schreiben
Krusty
3
@Krusty Imlement ist eine Methode isMyControlVisible () in Ihrem Präsentator, bei der Sie Ihre Domänenlogik verwenden, um true oder false zurückzugeben. Binden Sie an diese Methode.
Artkoenig
1
Ich denke, wenn Sie zu viele boolesche Variablen haben, ist diese Lösung in Ordnung. Andernfalls hätte Ihr Code viel ObservableBoolean.set
Lester
@artkoenig dann müssten Sie diese zusätzlichen Booleschen Werte überall dort beibehalten, wo Sie auf das Layout verweisen. Quelle von Fehlern.
Ali Kazi
36

Liste der HTML-Entitäten

Sie können & oder eine andere HTML-Entität in XML nicht verwenden. Sie müssen also einen Escape-Charakter verwenden.

android:text="@{(1==1 &amp;&amp; 2>0) ? `true` : `false`}"

In Android häufig verwendete HTML-Zeichenentitäten:

+--------+----------------------------+--+--+--+
| Symbol | Equivalent HTML Entity     |  |  |  |
+--------+----------------------------+--+--+--+
| >      | &gt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| <      | &lt;                       |  |  |  |
+--------+----------------------------+--+--+--+
| "      | &quot;, &ldquo; or &rdquo; |  |  |  |
+--------+----------------------------+--+--+--+
| '      | &apos;, &lsquo; or &rsquo; |  |  |  |
+--------+----------------------------+--+--+--+
| }      | &#125;                     |  |  |  |
+--------+----------------------------+--+--+--+
| &      | &amp;                      |  |  |  |
+--------+----------------------------+--+--+--+
| space  | &#160;                     |  |  |  |
+--------+----------------------------+--+--+--+

Hier ist eine vollständige Liste der HTML-Entitäten.

Khemraj
quelle
17

Das Entkommen von && im Layout-Markup ist eine sehr schlechte Lösung. Es ist besser, eine Methode für das (Ansichts-) Modellobjekt zu erstellen:

android:visibility="@{user.adult ? View.VISIBLE : View.GONE}"

public boolean isAdult() {
    return age >= 18;
}
Ollie C.
quelle
4
Dies ist zwar eine gute Lösung, wird jedoch leider nicht aufgerufen, wenn sich der Variablenwert ändert (notifyPropertyChanged) und die Sichtbarkeit nicht aktualisiert wird.
Bernd Kampl
2
@BerndKampl VerwendungObservableBoolean isAdult
S1ngoooor
Dies wird nicht funktionieren, es wird nur einmal aufgerufen!
CodingTT
@BerndKampl wie man es benutzt, es wird immer noch einmal aufgerufen
CodingTT
@CodingTT Schauen Sie sich meine Antwort an. Sie benötigen irgendwo einen Aufruf von notifyPropertyChanged, um sie zu aktualisieren.
Bernd Kampl
3

Die beste Lösung, die ich für dieses Problem finden konnte, war die Einführung einer neuen bindbaren Methode.

Vor:

item_recyclerview.xml::

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.lastAddedItem &amp;&amp; !myViewModel.myDataModelClass.editTextDisabled}"
/>

MyDataModelClass: (was in meinem Ansichtsmodell gehalten wird)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
}

Nach dem:

item_recyclerview.xml::

<EditText
...
android:enabled="@{myViewModel.myDataModelClass.enableEditing}"
/>

MyDataModelClass: (was in meinem Ansichtsmodell gehalten wird)

...
private boolean lastAddedItem;
private boolean editTextDisabled;
...
@Bindable
public boolean isLastAddedItem() {
    return lastAddedItem;
}
public void setLastAddedItem(boolean lastAddedItem) {
    this.lastAddeditem = lastAddedItem;
    notifyPropertyChanged(BR.lastAddedItem);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEditTextDisabled() {
    return editTextDisabled;
}
public void setEditTextDisabled(boolean editTextDisabled) {
    this.editTextDisabled = editTextDisabled;
    notifyPropertyChanged(BR.editTextDisabled);
    notifyPropertyChanged(BR.isEnableEditing);
}
@Bindable
public boolean isEnableEditing() {
    return isLastAddedItem() && !isEditTextDisabled();
}
Bernd Kampl
quelle
Dieser Code verwendet BaseObservable-Klassen, BR ist die generierte Bindungsklasse. Eine ausführlichere Erklärung finden Sie in diesem Beitrag: medium.com/@jencisov/…
Bernd Kampl