android databinding using "&&" logical operator
Asked Answered
H

5

183

I am trying to use the and "&&" operator in xml using Android databinding,

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

but I got the compilation error:

Error:Execution failed for task ':app:dataBindingProcessLayoutsDevDebug'. org.xml.sax.SAXParseException; systemId: file:/Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; lineNumber: 106; columnNumber: 89; The entity name must immediately follow the '&' in the entity reference.

and red highlight error in android studio "unescaped & or non terminated character".

So how should I fix this?

Edit: found the answer, these character needs to be escaped:

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'
Husain answered 11/5, 2016 at 3:54 Comment(1)
I have noticed that I can use ">" and "<" in layout xml files.Cockoftherock
A
312

&& should be rendered as &amp;&amp;.

The official data binding guide has examples of comparison operators where these XML entities are used, for example

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

Edit

The example expressions I mentioned in the answer disappeared from the English version of the docs since this answer was written. They do survive in some outdated non-English versions of the docs such as the Spanish version.

Either way, the original answer is still valid, because the use of XML entities in XML is standard in XML and has nothing to do with Android itself.

Accuse answered 11/5, 2016 at 4:11 Comment(5)
Don't use domain logic in binding expressions, you have preseters/controllers for this.Iphagenia
@ArtjomKönig what about if you have to hide/show some controls in the UI? I use data binding library to NOT write UI codeNoelianoell
@Noelianoell Imlement a method isMyControlVisible() in your presenter, where you use your domain logic to return true or false back. Bind to this method.Iphagenia
I think If you have too many boolean variables this solutions is fine. Otherwise your code would have plenty of ObservableBoolean.setSybil
@Iphagenia then you would have to maintain those extra booleans everywhere you reference to the layout. Source of bugs.Pantelleria
P
68

List of HTML entities

You can not use & or some other HTML entity in XML. So you have to use escaping character.

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

HTML Character entities often used in Android:

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

Here is a complete list of HTML entities.

Publea answered 31/7, 2018 at 11:54 Comment(0)
S
22

Escaping && in the layout mark-up is a very poor solution. It is better to create a method on the (view)model object:

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

public boolean isAdult() {
    return age >= 18;
}
Spearwort answered 30/9, 2016 at 10:4 Comment(6)
While this is a good solution, it unfortunately does not get called when the variable value changes (notifyPropertyChanged) and the visibility will not be updated.Innards
@BerndKampl Use ObservableBoolean isAdultAcquittal
This not going to work, it will only get called once!Quandary
@BerndKampl how to use it, it is still get called onceQuandary
@Quandary look at my Answer, you will need a notifyPropertyChanged call somewhere to update it.Innards
@BerndKampl what they are suggesting is to create an ObservableBoolean whose value is updated when the age value is updated.Poverty
I
5

The best solution that I could come up with for this problem was introducing a new Bindable method.

Before:

item_recyclerview.xml:

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

MyDataModelClass: (which is being held in my viewmodel)

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

After:

item_recyclerview.xml:

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

MyDataModelClass: (which is being held in my viewmodel)

...
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();
}
Innards answered 22/12, 2016 at 12:43 Comment(1)
That code is using BaseObservable classes, BR is the generated binding class. See this post for a more detailed explanation: medium.com/@jencisov/…Innards
S
0

Try 'compareTo' method in the XML like

android:visibility=${viewModel.intValue.compareTo(0) == -1 ? View.GONE : View.VISIBLE}"
Snotty answered 21/5, 2022 at 22:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.