enlace de datos de Android con el operador lógico "&&"

131

Estoy tratando de usar el operador y "&&" en xml usando el enlace de datos de Android,

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

pero recibí el error de compilación:

Error: Falló la ejecución de la tarea ': aplicación: dataBindingProcessLayoutsDevDebug'. org.xml.sax.SAXParseException; systemId: archivo: /Users/path/app/build/intermediates/res/merged/dev/debug/layout/fragment_space.xml; número de línea: 106; columnNumber: 89; El nombre de la entidad debe seguir inmediatamente el '&' en la referencia de la entidad.

y error de resaltado en rojo en el estudio de Android "personaje sin escape y / o sin terminar".

Entonces, ¿cómo debo solucionar esto?

Editar: encontró la respuesta, estos personajes deben escaparse:

'&' --> '&'

'<' --> '&lt;'

'>' --> '&gt;'
David Cheung
fuente
He notado que puedo usar ">" y "<" en los archivos xml de diseño.
Hong

Respuestas:

234

&&debe presentarse como &amp;&amp;.

La guía oficial de enlace de datos tiene ejemplos de operadores de comparación donde se utilizan estas entidades XML, por ejemplo

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

Editar

Las expresiones de ejemplo que mencioné en la respuesta desaparecieron de la versión en inglés de los documentos ya que esta respuesta fue escrita. Sobreviven en algunas versiones obsoletas de los documentos que no están en inglés, como la versión en español.

De cualquier manera, la respuesta original sigue siendo válida, porque el uso de entidades XML en XML es estándar en XML y no tiene nada que ver con el propio Android.

Leo apoya a Monica Cellio
fuente
12
No use la lógica de dominio en expresiones de enlace, tiene preseters / controladores para esto.
artkoenig
2
@ ArtjomKönig, ¿qué pasa si tiene que ocultar / mostrar algunos controles en la interfaz de usuario? Yo uso la biblioteca de enlace de datos para NO escribir código de interfaz de usuario
Krusty
3
@Krusty Imlement, un método esMyControlVisible () en su presentador, donde utiliza la lógica de su dominio para devolver verdadero o falso. Ate a este método.
artkoenig
1
Creo que si tienes demasiadas variables booleanas, esta solución está bien. De lo contrario, su código tendría un montón de ObservableBoolean.set
Lester
@artkoenig, entonces tendría que mantener esos booleanos adicionales en todas partes donde haga referencia al diseño. Fuente de errores.
Ali Kazi
36

Lista de entidades HTML

No puede usar & o alguna otra entidad HTML en XML. Entonces tienes que usar el carácter de escape.

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

Entidades de caracteres HTML de uso frecuente en Android:

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

Aquí hay una lista completa de entidades HTML.

Khemraj
fuente
17

Escapar && en el marcado de diseño es una solución muy pobre. Es mejor crear un método en el objeto del modelo (ver):

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

public boolean isAdult() {
    return age >= 18;
}
Ollie C
fuente
44
Si bien esta es una buena solución, desafortunadamente no se llama cuando cambia el valor de la variable (notifyPropertyChanged) y la visibilidad no se actualizará.
Bernd Kampl
2
@BerndKampl UseObservableBoolean isAdult
S1ngoooor
¡Esto no va a funcionar, solo se llamará una vez!
CodificaciónTT
@BerndKampl cómo usarlo, todavía se llama una vez
CodingTT
@CodingTT mire mi respuesta, necesitará una llamada de notificación de propiedad cambiada en algún lugar para actualizarla.
Bernd Kampl
3

La mejor solución que pude encontrar para este problema fue introducir un nuevo método Bindable.

Antes de:

item_recyclerview.xml:

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

MyDataModelClass: (que se lleva a cabo en mi modelo de vista)

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

Después:

item_recyclerview.xml:

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

MyDataModelClass: (que se lleva a cabo en mi modelo de vista)

...
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
fuente
Ese código está usando clases BaseObservable, BR es la clase de enlace generada. Consulte esta publicación para obtener una explicación más detallada: medium.com/@jencisov/…
Bernd Kampl