ejemplos - recorrer enum java
¿Cómo establecer el atributo enum por valor en lugar de nombre en el diseño de Android? (2)
No puedo establecer la enumeración por valor sino solo por nombre
Eso no es del todo cierto. No podría establecer el valor con DataBinding ni siquiera por su nombre, lo que sucede es que el valor de un atributo definido en un xml se pasa a la View
través del constructor. Una View
puede tener tanto un atributo como un definidor, pero ese no es necesariamente el caso. Por ejemplo, si establece un valor para android:text
de un TextView
, ese valor se establece en com.android.internal.R.styleable.TextView_text
que luego se recupera del AttributeSet
en el constructor. Si usa DataBinding, se llama a setText()
, pero son 2 cosas completamente diferentes, la característica es la misma pero no están relacionadas en el código.
Dado que no puede modificar MyInnerView
y que no hay un configurador al que pueda llamar myAttr
, su única opción es pasarlo a través del constructor. El enlace de datos simplemente no es factible, incluso con un BinderAdapter no podría establecer el valor en AttributeSet
porque la View
ya está instanciada en ese punto.
Opción 1 - temas
Definir un nuevo atributo.
<attr name="MyInnerViewAttrValue" format="integer" />
Luego resuelva este atributo con un estilo, por ejemplo, podría tener
<style name="AppTheme.Foo">
<item name="MyInnerViewAttrValue">0</item>
</style>
<style name="AppTheme.Bar">
<item name="MyInnerViewAttrValue">1</item>
</style>
Colócalo en el diseño xml.
<com.example.MyInnerView
...
app:myAttr="?attr/MyInnerViewAttrValue" />
Y luego llame a setTheme(int)
en la Activity
antes de que las vistas sean instanciadas.
Opción 2 - BindingAdapter personalizado
Si quisiera establecer su valor Enlace de datos (porque tenía un configurador o porque quería piratear MyInnerView
con reflexión), entonces tendría que crear un BindingAdapter personalizado, por ejemplo.
@BindingAdapter("myAttrValue")
public static void setMyAttr(MyInnerView myInnerView, int value) {
switch (value) {
case 0:
myInnerView.foo();
break;
default:
myInnerView.bar();
}
}
Luego en el diseño xml
<com.example.lelloman.dummy.MyInnerView
...
myAttrValue="@{model.attr}" />
Y dale el valor int
desde tu ViewModel
public class MyInnerViewModel {
public int getAttr() {
return 1234;
}
}
Tengo una vista personalizada sosteniendo otra. Jerarquía:
MyOuterView
->MyInnerView
MyInnerView
tiene un atributo de enumeración como:
<attr name="myAttr" format="enum">
<enum name="foo" value="0"/>
<enum name="bar" value="1"/>
</attr>
Entonces puedo instanciar el componente en MyOuterView
XML como:
<com.example.MyInnerView
....
app:myAttr="foo"/>
Que funciona, por supuesto. El MyOuterView
ofrece un argumento para la personalización en sí. Basado en este argumento, quiero establecer el argumento de MyInnerView
.
El comportamiento deseado es que puedo trabajar con el enlace de datos como:
<com.example.MyInnerView
....
app:myAttr="@{data.getMyAttr()}"/>
donde getMyAttr()
ve como:
public int getMyAttr() {
return myAttr; // returns 0 or 1
}
El resultado es un problema de compilación.
**** / error de enlace de datos **** msg: no se puede encontrar el configurador para el atributo ''app: myAttr'' con el tipo de parámetro int en com.example.MyInnerView
Así que obviamente no puedo establecer la enumeración por valor sino solo por nombre. ¿Alguna idea además de crear el MyInnerView
programáticamente? Tenga en cuenta que no puedo cambiar MyInnerView
.
Desafortunadamente, puede usar el nombre del atributo como app:myAttr="@{...}"
solo si hay un configurador para eso y este definidor se asigna al nombre del atributo o se puede resolver por su nombre. En su caso, si este atributo se usa solo en el constructor de View y view no tiene ningún método público para cambiar esto, todavía tiene algunas soluciones posibles: extienda View e implemente la lógica para personalizar la vista como lo hace este atributo (si es posible) haz BindingAdapter y usa Reflection (si es posible). - crea tu propia vista copiando y pegando y arreglando)