J'utilise la nouvelle liaison de données Android et cela fonctionne très bien. Je suis capable d'effectuer la liaison de données en utilisant EditText, TextView, Radio et checkbox. Maintenant, je ne suis pas capable de faire la liaison de données dans spinner.
Vous avez trouvé un indice dans le lien ci-dessous: Android spinner data binding with xml layout
Mais, toujours pas en mesure de trouver la solution. Vous devez également effectuer la liaison de données bidirectionnelle. Devrait refléter la valeur sélectionnée des données de rotation.
Quelqu'un peut-il s'il vous plaît me montrer avec un exemple?
Voici mon code xml
:
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:app="http://schemas.Android.com/tools"
xmlns:card_view="http://schemas.Android.com/apk/res-auto">
<data>
<import type="Android.view.View" />
<variable
name="viewModel"
type="com.ViewModels.model" />
</data>
<Spinner
Android:id="@+id/assessmemt_spinner"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_alignParentRight="true"
Android:layout_margin="@dimen/carview_margin"
Android:layout_toRightOf="@+id/text_bp"
Android:drawSelectorOnTop="true"
Android:spinnerMode="dropdown"
Android:visibility="@{viewModel.type.equals(@string/spinner_type)? View.VISIBLE : View.GONE}" />
</layout>
Voir le modèle:
public class AssessmentGetViewModel {
private String valueWidth;
private ArrayList<String> values;
private String type;
public String getValueWidth() { return this.valueWidth; }
public void setValueWidth(String valueWidth) { this.valueWidth = valueWidth; }
public ArrayList<String> getvalues() { return this.values; }
public void setvalues(ArrayList<String> values) { this.values = values; }
public String gettype() { return this.type; }
public void settype(String type) { this.type = type; }
}
J'ai trouvé quelque chose qui pourrait être utile mais ce n'est pas dans la documentation officielle pour la liaison de données bidirectionnelle.
1. '@ =' utilisation pour la liaison de données bidirectionnelle
2. La liaison de données personnalisée bidirectionnelle nécessite les annotations "BindingAdapter" et "InverseBindingAdapter" pour y parvenir.
Pour le premier élément, de nombreux blogueurs ont montré l'utilisation de "@ =" pour la liaison de données bidirectionnelle. https://halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-Android/
Pour le second élément, comme @George Mound a répondu ici ( le curseur de texte d'édition est réinitialisé à gauche lorsque le texte par défaut d'edittext est une valeur flottante ), le texte d'édition peut être lié dans les deux sens à l'aide de l'annotation "BindingAdapter" et "InverseBindingAdapter" .
En suivant les instructions, vous pouvez créer votre méthode de reliure bidirectionnelle pour spinner.
Tout d'abord, créez votre ViewModel ou utilisez Pojo
ViewModel
public class ViewModel {
private ObservableField<String> text;
public ViewModel() {
text = new ObservableField<>();
}
public ObservableField<String> getText() {
return text;
}
}
Pojo
public class ViewModel {
private String text;
public String getText() {
return text;
}
public void setText(String text)
{
this.text = text;
}
}
Deuxièmement, ajoutez-le dans votre XML.
<Android.support.v7.widget.AppCompatSpinner
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:entries="@array/days"
bind:selectedValue="@={viewModel.text}"/>
Troisièmement, ajoutez votre liaisonUtil
public class SpinnerBindingUtil {
@BindingAdapter(value = {"selectedValue", "selectedValueAttrChanged"}, requireAll = false)
public static void bindSpinnerData(AppCompatSpinner pAppCompatSpinner, String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
pAppCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
newTextAttrChanged.onChange();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
if (newSelectedValue != null) {
int pos = ((ArrayAdapter<String>) pAppCompatSpinner.getAdapter()).getPosition(newSelectedValue);
pAppCompatSpinner.setSelection(pos, true);
}
}
@InverseBindingAdapter(attribute = "selectedValue", event = "selectedValueAttrChanged")
public static String captureSelectedValue(AppCompatSpinner pAppCompatSpinner) {
return (String) pAppCompatSpinner.getSelectedItem();
}
}
Comme vous l'avez vu, il a utilisé "selectedValue" comme variable pour la valeur sélectionnée par défaut, mais que signifie "selectedValueAttrChanged"? Je pensais que celui-ci est délicat (je ne sais pas pourquoi il n'est pas nul quand il est appelé), il n'est pas nécessaire de l'ajouter au xml puisqu'il ne s'agit que du rappel pour l'écoute de l'élément modifié dans le compteur. Ensuite, vous définissez onItemSelectedListener et l'appelez la fonction InverseBindingListener onchange () (Documentation et exemple ici: https://developer.Android.com/reference/Android/databinding/InverseBindingAdapter.html ) L'événement par défaut sera "Android: textAttrChanged" et si vous souhaitez avoir une liaison bidirectionnelle personnalisée, inversebind, vous devez utiliser l'attribut avec le suffixe "AttrChanged".
La valeur par défaut pour event est le nom de l'attribut avec le suffixe "Attrchangé". Dans l'exemple ci-dessus, la valeur par défaut aurait été Android: textAttrChanged même s'il n'a pas été fourni.
Enfin, dans votre activité et votre string.xml
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding lBinding = DataBindingUtil.inflate(LayoutInflater.from(this), R.layout.activity_main, null, false);
mViewModel = new ViewModel();
mViewModel.getText().set("Wednesday");
lBinding.setViewModel(mViewModel);
lBinding.setHandler(new Handler());
setContentView(lBinding.getRoot());
}
string.xml
<array name="days">
<item name="Mon">Monday</item>
<item name="Tue">Tuesday</item>
<item name="Wed">Wednesday</item>
</array>
Lorsque vous exécutez le code, "Mercredi" sera affiché comme valeur par défaut pour le compteur. J'espère que cela peut aider pour beaucoup de gens
Vous pouvez le faire simplement avec onItemSelected et obtenir la position sélectionnée et le texte de l’article sélectionné.
1) ajoutez onItemSelected attribut à votre disque comme ci-dessous:
<Spinner
Android:id="@+id/spinner"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:entries="@array/item_list"
Android:onItemSelected="@{(parent,view,pos,id)->viewModel.onSelectItem(parent,view,pos,id)}"/>
2) maintenant vous devez ajouter cette méthode à votre viewModel :
public void onSelectItem(AdapterView<?> parent, View view, int pos, long id)
{
//pos get selected item position
//view.getText() get lable of selected item
//parent.getAdapter().getItem(pos) get item by pos
//parent.getAdapter().getCount() get item count
//parent.getCount() get item count
//parent.getSelectedItem() get selected item
//and other...
}
tableau pourrait être quelque chose comme cela doit enregistrer dans values / item_list.xml :
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="item_list">
<item>item1</item>
<item>item2</item>
<item>item3</item>
</array>
</resources>
Lorsque la mise en page est dessinée, onItemSelected est appelé, vous pouvez définir la valeur initiale:
parent.setSelection(1); //1 is position of initializing value
Android:selectedItemPosition="@={item.selectedItemPosition}"
C'est tout! Pas besoin de personnaliser BindingAdapter.
Spinner prend déjà en charge la liaison bidirectionnelle par les attributs
selection
etselectedItemPosition
. Voir Documentation AndroidVous devez simplement utiliser la liaison à deux voies
selectedItemPosition
pour que changer sur spinner réfléchir sur votre champ modèle.
Item.class
public class Item extends BaseObservable {
private int selectedItemPosition;
@Bindable
public int getSelectedItemPosition() {
return selectedItemPosition;
}
public void setSelectedItemPosition(int selectedItemPosition) {
this.selectedItemPosition = selectedItemPosition;
notifyPropertyChanged(BR.selectedItemPosition);
}
}
activity_main.xml
<variable
name="item"
type="com.sample.data.Item"/>
<Android.support.v7.widget.AppCompatSpinner
...
Android:entries="@array/items"
Android:selectedItemPosition="@={item.selectedItemPosition}"
>
MainActivity.Java
public class MainActivity extends AppCompatActivity {
ActivityMainBinding binding;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setItem(new Item());
binding.getItem().setSelectedItemPosition(4); // this will change spinner selection.
System.out.println(getResources().getStringArray(R.array.items)[binding.getItem().getSelectedItemPosition()]);
}
}
Si vous avez besoin d’obtenir un élément sélectionné de votre code à tout moment, utilisez cette commande.
binding.getItem().getSelectedItemPosition(); // get selected position
getResources().getStringArray(R.array.items)[binding.getItem().getSelectedItemPosition()]) // get selected item
Définissez votre variable @Bindable si vous devez la modifier par programme.
binding.getItem().setSelectedItemPosition(4);
Sinon, vous pouvez supprimer @Bindable et notifyPropertyChanged(BR.selectedItemPosition);
.
Vous pouvez utiliser n'importe lequel de BaseObservable ou ObservableField ou Live Data. C'est à toi de decider. J'utilise BaseObservable parce que c'est très simple., étendez simplement BaseObservable et tous les champs sont maintenant observables.
Voir ma réponse pour obtenir la liaison de données la plus simple possible avec spinner. En effet, nous avons besoin d'un adaptateur pour effectuer d'autres tâches.
Le code XML est là.
Java:
// Data binding
ActivityParentsRegBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_parents_reg);
binding.setCities(ConstData.getCitiesList());
@ Long Ranger J'aime beaucoup votre réponse, mais je pense qu'il y a quelque chose que nous devons faire pour rompre la boucle.
@BindingAdapter(value = {"bind:selectedValue", "bind:selectedValueAttrChanged"}, requireAll = false)
public static void bindSpinnerData(AppCompatSpinner pAppCompatSpinner, final String newSelectedValue, final InverseBindingListener newTextAttrChanged) {
pAppCompatSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if(newSelectedValue != null && newSelectedValue.equals(parent.getSelectedItem())){
return;
}
newTextAttrChanged.onChange();
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
if (newSelectedValue != null) {
int pos = ((ArrayAdapter<String>) pAppCompatSpinner.getAdapter()).getPosition(newSelectedValue);
pAppCompatSpinner.setSelection(pos, true);
}
}