привязка данных Android с помощью логического оператора «&&»

132

Я пытаюсь использовать оператор и "&&" в xml, используя привязку данных Android,

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

но я получил ошибку компиляции:

Ошибка: не удалось выполнить задачу ': 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; Имя объекта должно сразу следовать за символом "&" в ссылке на объект.

и красная ошибка выделения в студии Android «неэкранированный и или не завершенный символ».

Так как мне это исправить?

Изменить: нашел ответ, нужно экранировать этот символ:

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'
Дэвид Чунг
источник
Я заметил, что могу использовать ">" и "<" в файлах макета xml.
Гонконг

Ответы:

234

&&должен отображаться как &amp;&amp;.

В официальном руководстве по привязке данных есть примеры операторов сравнения, в которых используются эти XML-сущности, например

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

редактировать

Примеры выражений, которые я упомянул в ответе, исчезли из английской версии документов, так как этот ответ был написан. Они действительно сохранились в некоторых устаревших неанглоязычных версиях документов, например в испанской.

В любом случае исходный ответ по-прежнему действителен, поскольку использование сущностей XML в XML является стандартом для XML и не имеет ничего общего с самим Android.

Лев поддерживает Монику Челлио
источник
12
Не используйте логику домена в выражениях привязки, для этого у вас есть презетеры / контроллеры.
artkoenig 09
2
@ ArtjomKönig, а что если вам нужно скрыть / показать некоторые элементы управления в пользовательском интерфейсе? Я использую библиотеку привязки данных, чтобы НЕ писать код пользовательского интерфейса
Красти
3
@Krusty Внедрите метод isMyControlVisible () в своем презентаторе, где вы используете логику своего домена, чтобы вернуть обратно истину или ложь. Привяжите к этому методу.
artkoenig
1
Я думаю, что если у вас слишком много логических переменных, это решение подойдет. В противном случае в вашем коде было бы много ObservableBoolean.set
Лестер,
@artkoenig, тогда вам придется поддерживать эти дополнительные логические значения везде, где вы ссылаетесь на макет. Источник ошибок.
Али Кази
36

Список объектов HTML

Вы не можете использовать & или какой-либо другой объект HTML в XML. Итак, вам нужно использовать экранирующий символ.

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

Сущности символов HTML, часто используемые в Android:

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

Вот полный список объектов HTML.

Khemraj
источник
17

Экранирование && в разметке макета - очень плохое решение. Лучше создать метод на объекте модели (view):

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

public boolean isAdult() {
    return age >= 18;
}
Олли С
источник
4
Хотя это хорошее решение, оно, к сожалению, не вызывается при изменении значения переменной (notifyPropertyChanged) и видимость не обновляется.
Бернд Кампл
2
@BerndKampl UseObservableBoolean isAdult
S1ngoooor
Это не сработает, оно будет вызвано только один раз!
CodingTT
@BerndKampl, как его использовать, он все равно вызывается один раз
CodingTT
@CodingTT посмотрите мой ответ, вам понадобится вызов notifyPropertyChanged где-нибудь, чтобы обновить его.
Бернд Кампл
3

Лучшее решение, которое я мог придумать для этой проблемы, - это введение нового метода Bindable.

Перед:

item_recyclerview.xml:

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

MyDataModelClass: (который проводится в моей модели просмотра)

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

После:

item_recyclerview.xml:

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

MyDataModelClass: (который проводится в моей модели просмотра)

...
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();
}
Бернд Кампл
источник
Этот код использует классы BaseObservable, BR - это сгенерированный класс привязки. См. Этот пост для более подробного объяснения: medium.com/@jencisov/…
Бернд Кампл