2016-05-18 6 views
5

sono riuscito a legare filatore a ArrayList di objects, ora ho bisogno di fare in modo che quando si seleziona determinato articolo dal filatore che rifletta a ViewModel (setter viene chiamato e imposta il valore di una variabile di quanto selezionato indice è in filatore)come 2 vie legano filatore selezionato valore al valore nel arraylist

sono riuscito a farlo funzionare il contrario, il valore da viewmodel viene riflesso view (simili How to use DataBindingUtil with an Android spinner?).

rilevanti xml

<data> 
<variable 
      name="spinnerList" 
      type="com.example.root.proj.viewmodels.MonumentTypeVMList"/> 
</data> 


<Spinner 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      bind:spinnerbind="@{spinnerList.list}" 
      bind:selection="@{spinnerList.selection}" 
      ></Spinner> 

personalizzato vincolante

@BindingAdapter("bind:selection") 
public static void bindSelection(Spinner spinner, int position) { 
    spinner.setSelection(position); 
} 
+0

si può condividere il modello/classe POJO? –

risposta

3

È possibile utilizzare Inverse Binding per raggiungere questo obiettivo. Sarà necessario definire due collegamenti personalizzati.

  1. Per ottenere l'ultimo valore dallo spinner e impostare nel modello.
  2. Attiva un evento quando viene selezionato un nuovo valore nella casella.

Per ottenere il valore selezionato dallo spinner, aggiungere questo metodo alle associazioni personalizzate.

@InverseBindingAdapter(attribute = "selection", event = "selectionAttrChanged") 
    public static String getSelectedValue(AdapterView view) { 
    return (String) view.getSelectedItem(); 
    } 

per attivare un evento quando si seleziona nuovo valore nell'uso filatore

@BindingAdapter(value = {"selection", "selectionAttrChanged", "adapter"}, requireAll = false) 
    public static void setAdapter(AdapterView view, String newSelection, final InverseBindingListener bindingListener, ArrayAdapter adapter) { 
    view.setAdapter(adapter); 
    view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
     @Override 
     public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
     bindingListener.onChange(); 
     } 

     @Override 
     public void onNothingSelected(AdapterView<?> parent) { 
     //Nothing 
     } 
    }); 
    if (newSelection != null) { 
     int pos = ((ArrayAdapter) view.getAdapter()).getPosition(newSelection); 
     view.setSelection(pos); 
    } 
    } 

Ora nel tuo file di layout basta usare il sopra vincolante:

<Spinner 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     app:adapter="@{AdapterFactory.getAdapter(context)}" 
     app:selection="@={model.selectedValue}"/> 
5

Praticamente la stessa come risposta di Ajit ma utilizzando Android: voci invece di unire un adattatore.

    <android.support.v7.widget.AppCompatSpinner 
        android:id="@+id/typeSpinner" 
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" 
        android:entries="@{vehicle.types}" 
        android:selectedItemPosition="@={vehicle.selectedTypePosition}"> 

Poi la mia classe osservabile

@InverseBindingMethods({ 
     @InverseBindingMethod(type = AppCompatSpinner.class, attribute = "android:selectedItemPosition"), 
    }) 
    class Vehicle extends BaseObservable { 

    String[] types = getResources().getStringArray(R.array.service_types); 

    String type = null; 

    @Bindable 
    public String getType() { 
     return type; 
    } 

    public void setType(String type) { 
     this.type = type; 
     notifyPropertyChanged(BR.type); 
    } 

    Integer selectedTypePosition = 0; 

    @Bindable 
    public Integer getSelectedTypePosition() { 
     return selectedTypePosition; 
    } 

    public void setSelectedTypePosition(Integer selectedTypePosition) { 
     this.selectedTypePosition = selectedTypePosition; 
     type = types[selectedTypePosition]; 

    } 

    @BindingAdapter("selectedItemPositionAttrChanged") 
    void setSelectedItemPositionListener(AppCompatSpinner view, final InverseBindingListener selectedItemPositionChange) { 
     if (selectedItemPositionChange == null) { 
      view.setOnItemSelectedListener(null); 
     } else { 
      view.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 

       @Override 
       public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 
        selectedItemPositionChange.onChange(); 
       } 

       @Override 
       public void onNothingSelected(AdapterView<?> parent) { 

       } 
      }); 
     } 
    } 

    @InverseBindingAdapter(attribute = "selectedItemPosition") 
    Integer getSelectedItemPosition(AppCompatSpinner spinner) { 
     return spinner.getSelectedItemPosition(); 
    } 

} 

semplificato questo dalla mia implementazione e non l'ho provato. Dovrebbe funzionare però ...

+2

Ho ricevuto l'errore come: Errore: (43, 10) errore: @BindingAdapter sull'elemento non valido: setSelectedItemPositionListener (android.support.v7.widget.AppCompatSpinner, android.databinding.InverseBindingListener) –

5

Una soluzione ancora più semplice (a mio parere) è presentata in this question, la chiave è l'uso del selectedItemPostion attribute of the Spinner che non è nel codice incluso con la domanda ma è nel repository che collega a: android:selectedItemPosition="@={model.position}"

Ho utilizzato l'approccio sopra con successo. Ciò richiede di fare la mappatura dalla posizione agli effettivi elenchi di selezione, ma ho comunque dovuto farlo per il mio caso d'uso.

+0

perché fornisce avviso di attributo sconosciuto – Killer

+1

perché AS non ha ancora una grande integrazione con i databinding. E quel particolare punto è un problema abbastanza difficile, perché AS ha bisogno di convalidare un processore di annotazione post del file di layout, che è ovviamente difficile. – user3175580

0

implementare due modo vincolante per Spinner

1) Utilizzare attributo personalizzato e aggiungere l'espressione vincolante per associare la proprietà di modello di dati per l'attributo personalizzato a due vie, nel seguente codice, si legano: paymentMode è attributo personalizzato.

<android.support.v7.widget.AppCompatSpinner 
    . . . 
    bind:pmtOpt="@={accountSettings.defaultPaymentOption}" 
    app:adapter="@{spinAdapter}" /> 

2) allora per fornire il comportamento o metodo setter che deve essere usato quando i dati assorbente (modello di dati a trottola) si verifica per questo attributo, BindingAdapter deve essere definito. Quando si verifica l'associazione, è necessario impostare il valore selezionato predefinito e aggiungere il listener selezionato all'arricchitore e nel listener quando si verifica l'evento di selezione dell'elemento, è necessario informare il framework di associazione dati per acquisire il valore utilizzando InverseBindingListener per iniziare il binding inverso.

@BindingAdapter(value = {"bind:paymentMode", 
"bind:paymentModeAttrChanged"}, requireAll = false) 
public static void setPaymentMode(final AppCompatSpinner spinner, 
     final String selectedPmtMode, 
     final InverseBindingListener changeListener) { 
    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 
     @Override 
     public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { 
      changeListener.onChange(); 
     } 
     @Override 
     public void onNothingSelected(AdapterView<?> adapterView) { 
      changeListener.onChange(); 
     } 
    }); 

    spinner.setSelection(getIndexOfItem(spinner, selectedPmtMode)); 

} 

3) Definire legame inversa adattatore (ogiva a modello di dati) che viene utilizzato da quadro per acquisire il valore selezionato dall'utente e impostarlo modello di dati. Questo viene chiamato quando InverseBindingListener riceve la notifica.

@InverseBindingAdapter(attribute = "bind:paymentMode", 
      event = "bind:paymentModeAttrChanged") 
    public static String getPaymentMode(final AppCompatSpinner spinner) { 
     return (String)spinner.getSelectedItem(); 
    } 

Per ulteriori informazioni sull'associazione dei dati e filatore a due vie di attuazione vincolante riferimento al http://www.zoftino.com/android-data-binding-library-tutorial

Problemi correlati