¿Cómo enlazar DataBinding de Android a Menú?

¿Como soporta el menú de vinculación de datos en android? Escribo este código, pero error: "Error: (16, 26) Ningún tipo de recurso especificado (en 'visible' con el valor '@ {item.visible}')."

<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="item" type="ru.dixy.ubiworkerchecklistsmobile.Models.Fact"/> <import type="android.view.View"/> </data> <item android:id="@+id/compliteitem" android:title="mybutton" android:icon="@drawable/complite" android:visible="@{item.visible}" app:showAsAction="ifRoom" /> </menu> 

"En este momento, la vinculación de datos es sólo para los recursos de diseño, no los recursos del menú"

Sin embargo, el comportamiento se puede lograr con Observable.OnPropertyChangedCallback . Primero debe definir OnPropertyChangedCallback:

 private final Observable.OnPropertyChangedCallback propertyChangedCallback = new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { getActivity().invalidateOptionsMenu(); } }; 

Suponiendo que tiene un modelo vinculante para Fact en su fragmento:

 <variable name="item" type="ru.dixy.ubiworkerchecklistsmobile.Models.Fact"/> 

Ahora usted necesita registrar propertyChangedCallback y anular su registro cuando haya terminado con él:

 @Override public void onStart() { super.onStart(); binding.getItem().addOnPropertyChangedCallback(propertyChangedCallback); } @Override public void onStop() { super.onStop(); binding.getItem().removeOnPropertyChangedCallback(propertyChangedCallback); } 

Ahora estamos listos para actualizar su estado de vista basado en el modelo de hechos :

 @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.menu_fact, menu); } @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); menu.findItem(R.id.compliteitem).setVisible(binding.getItem().isVisible()); } 

AFAIK, actualmente, el enlace de datos es sólo para recursos de diseño, no recursos de menú.

Me doy cuenta de que esta es una vieja pregunta, pero quería proporcionar una solución para que pueda ayudar a otros con el mismo problema. Esto se puede lograr usando una vista de acción para el elemento de menú. Requiere un pedacito justo de código, pero es un acercamiento que utiliza MVVM y se puede utilizar para cualquier enlace de datos.

Este es un ejemplo donde el icono muestra un recuento y cambia el fondo si el recuento es mayor que 0.

Definir el elemento de menú

Menu / main.xml

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/action_count" android:enabled="true" android:icon="@drawable/ic_menu_red_square" android:title="@string/count"/> </menu> 

Defina el modelo de vista para el elemento de menú.

 public class CountMenuViewModel extends BaseObservable { @Bindable int count; public CountMenuViewModel() {} public int getCount() { return count; } public void setCount(int count) { this.count = count; if (this.count < 0) { this.count = 0; } notifyPropertyChanged(BR.count); } @Bindable({"count"}) public @DrawableRes int getBackground() { if (count > 0) { return R.drawable.ic_menu_blue_square; } return R.drawable.ic_menu_red_square; } @Bindable({"count"}) public String getCountText() { if (count > 0) { return String.valueOf(count); } return null; } } 

Defina una devolución de llamada que será implementada por la actividad cuando se hace clic en el elemento de menú.

 public interface CountMenuActionCallback { void onCountMenuItemClicked(); } 

Cree un diseño para la vista de acción. El diseño utiliza la clase de modelo de vista y establece el texto para el recuento y el fondo. La interfaz de devolución de llamada se utiliza para OnClickListener para la vista de acción.

Layout / menu_action_count.xml

 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="data" type="com.botnerd.samplesapp.CountMenuViewModel" /> <variable name="callback" type="com.botnerd.samplesapp.CountMenuActionCallback" /> </data> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="@{() -> callback.onCountMenuItemClicked()}" android:background="?android:attr/actionBarItemBackground"> <ImageView android:layout_width="32dp" android:layout_height="32dp" android:layout_margin="4dp" android:src="@{data.background}" tools:src="@drawable/ic_menu_red_square" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@{data.countText}" tools:text="30" android:textSize="14dp" android:maxLines="1" android:textColor="@android:color/white" tools:ignore="SpUsage"/> </FrameLayout> </layout> 

Tenga en cuenta que se utiliza un adaptador de enlace personalizado para el atributo android:src . Este es un buen adaptador para configurar ImageView src a través de enlace de datos.

 @BindingAdapter({"android:src"}) public static void setSrc(ImageView view, @DrawableRes int resId) { try { view.setImageDrawable(ContextCompat.getDrawable(view.getContext(), resId)); } catch (Resources.NotFoundException e) { } } 

Por último, infle el menú y vincule el diseño de vista de acción en la actividad.

 @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); MenuItem menuItemCount = menu.findItem(R.id.action_count); MenuActionCountBinding binding = MenuActionCountBinding.inflate(getLayoutInflater()); binding.setData(mCountMenuViewModel); binding.setCallback(mCountMenuActionCallback); MenuItemCompat.setActionView(menuItemCount, binding.getRoot()); MenuItemCompat.setShowAsAction(menuItemCount, MenuItemCompat.SHOW_AS_ACTION_ALWAYS); return super.onCreateOptionsMenu(menu); } 

Para completar, aquí están todos los archivos de la muestra que no están definidos anteriormente.

Dibujable / ic_menu_blue_square.xml

 <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <padding android:bottom="4dp" android:left="4dp" android:right="4dp" android:top="4dp"/> <solid android:color="#000080"/> <corners android:radius="2dp"/> </shape> 

Dibujable / ic_menu_red_square.xml

 <shape xmlns:android="http://schemas.android.com/apk/res/android"> <padding android:bottom="4dp" android:left="4dp" android:right="4dp" android:top="4dp"/> <solid android:color="#800000"/> <corners android:radius="2dp"/> </shape> 

Layout / activity_main.xml

 <?xml version="1.0" encoding="utf-8"?> <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="callback" type="com.botnerd.samplesapp.MainActivityActionCallback" /> </data> <android.support.constraint.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.botnerd.samplesapp.MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="-" android:onClick="@{() -> callback.onMinusClicked()}" android:layout_marginStart="79dp" app:layout_constraintBaseline_toBaselineOf="@+id/button2" tools:layout_constraintBaseline_creator="1" tools:layout_constraintLeft_creator="1" app:layout_constraintLeft_toLeftOf="parent"/> <Button android:id="@+id/button2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+" android:onClick="@{() -> callback.onPlusClicked()}" tools:layout_constraintTop_creator="1" android:layout_marginStart="25dp" android:layout_marginTop="97dp" tools:layout_constraintLeft_creator="1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintLeft_toRightOf="@+id/button"/> </android.support.constraint.ConstraintLayout> </layout> 

MainActivityActionCallback.java

 public interface MainActivityActionCallback { void onPlusClicked(); void onMinusClicked(); } 

MainActivity.java

 public class MainActivity extends AppCompatActivity { ActivityMainBinding mBinding; CountMenuViewModel mCountMenuViewModel; CountMenuActionCallback mCountMenuActionCallback = new CountMenuActionCallback() { @Override public void onCountMenuItemClicked() { Toast.makeText(MainActivity.this, "Count clicked!", Toast.LENGTH_SHORT) .show(); } }; MainActivityActionCallback mActionCallback = new MainActivityActionCallback() { @Override public void onPlusClicked() { mCountMenuViewModel.setCount(mCountMenuViewModel.getCount() + 1); } @Override public void onMinusClicked() { mCountMenuViewModel.setCount(mCountMenuViewModel.getCount() - 1); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mCountMenuViewModel = new CountMenuViewModel(); mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); mBinding.setCallback(mActionCallback); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); MenuItem menuItemCount = menu.findItem(R.id.action_count); MenuActionCountBinding binding = MenuActionCountBinding.inflate(getLayoutInflater()); binding.setData(mCountMenuViewModel); binding.setCallback(mCountMenuActionCallback); MenuItemCompat.setActionView(menuItemCount, binding.getRoot()); MenuItemCompat.setShowAsAction(menuItemCount, MenuItemCompat.SHOW_AS_ACTION_ALWAYS); return super.onCreateOptionsMenu(menu); } } 
  • ObservableInt causa bloqueo en DataBinding Library
  • Edittext cursor restablecer a la izquierda después de la actualización de datos de datos de Android
  • Data Binding Android - El parámetro de tipo T tiene límites superiores incompatibles: ViewDataBinding y MainActivity
  • Error de enlace de datos: sólo se permite un elemento de diseño y un elemento de datos.
  • Cómo vincular el diseño con varios calificadores
  • El enlace de datos de Android no funciona con los atributos <merge>
  • Vinculación de datos de Android mediante etiqueta de inclusión
  • ¿Es posible unir un ObservableField a otro?
  • Ejemplo de enlace de datos de 2 vías de android no funcionan como se describe
  • Enlace de datos de Android layout_width y layout_height
  • Android - ¿Cómo enlazar un ListView a una colección de objetos personalizados?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.