Comme il prend en charge le menu Liaison de données dans Android? J'écris ce code, mais erreur: "Erreur: (16, 26) Aucun type de ressource spécifié (à 'visible' avec la valeur '@ {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>
"Pour le moment, la liaison de données concerne uniquement les ressources de structure, pas les ressources de menu"
Mais le comportement peut être obtenu avec Observable.OnPropertyChangedCallback . Vous devez d’abord définir OnPropertyChangedCallback:
private final Observable.OnPropertyChangedCallback propertyChangedCallback = new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable observable, int i) {
getActivity().invalidateOptionsMenu();
}
};
En supposant que vous ayez une liaison pour Fact model dans votre fragment:
<variable
name="item"
type="ru.dixy.ubiworkerchecklistsmobile.Models.Fact"/>
Maintenant, vous devez inscrire propertyChangedCallback et le désenregistrer quand vous avez terminé:
@Override
public void onStart() {
super.onStart();
binding.getItem().addOnPropertyChangedCallback(propertyChangedCallback);
}
@Override
public void onStop() {
super.onStop();
binding.getItem().removeOnPropertyChangedCallback(propertyChangedCallback);
}
Nous sommes maintenant prêts à mettre à jour votre état d'affichage en fonction du modèle Fact :
@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());
}
Pour autant que je sache, pour le moment, la liaison de données concerne uniquement les ressources de présentation, pas les ressources de menu.
Je me rends compte que c’est une vieille question, mais je voulais proposer une solution qui puisse aider les autres à résoudre le même problème. Ceci peut être réalisé en utilisant une vue d'action pour l'élément de menu. Cela nécessite pas mal de code, mais c'est une approche qui utilise MVVM et qui peut être utilisée pour toute liaison de données.
Ceci est un exemple où l'icône indique un nombre et change l'arrière-plan si le nombre est supérieur à 0.
Définir l'élément de menu
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>
Définissez le modèle de vue pour l'élément de menu.
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;
}
}
Définissez un rappel qui sera implémenté par l'activité lorsque l'utilisateur cliquera sur l'élément de menu.
public interface CountMenuActionCallback {
void onCountMenuItemClicked();
}
Créez une mise en page pour la vue d'action. La mise en page utilise la classe de modèle de vue et définit le texte pour le nombre et l'arrière-plan. L'interface de rappel est utilisée pour OnClickListener pour la vue d'action.
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>
Notez qu'un adaptateur de liaison personnalisé est utilisé pour l'attribut Android:src
. C'est un bon adaptateur pour configurer ImageView src par liaison de données.
@BindingAdapter({"Android:src"})
public static void setSrc(ImageView view, @DrawableRes int resId) {
try {
view.setImageDrawable(ContextCompat.getDrawable(view.getContext(), resId));
} catch (Resources.NotFoundException e) {
}
}
Enfin, gonflez le menu et liez la présentation de la vue d'action dans l'activité.
@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);
}
Pour être complet, voici tous les fichiers de l'exemple qui ne sont pas définis ci-dessus.
drawable/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>
drawable/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);
}
}