如何将spinner选中的值绑定到arraylist中的值

时间:2016-05-18 08:21:23

标签: android android-databinding

我设法将微调器绑定到ArrayList的{​​{1}},现在我需要在旋转器选择某个项目时将其反映到objects setter获取调用并将变量的值设置为所选索引在spinner中的值

我设法让它反过来工作,ViewModel的价值反映到viewmodel就像这个How to use DataBindingUtil with an Android spinner? )。

相关的xml

view

自定义绑定

<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>

4 个答案:

答案 0 :(得分:7)

与Ajit的答案几乎相同,但使用android:条目而不是绑定适配器。

                    <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}">

然后是我的可观察班级

    @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();
    }

}

从我的实施中简化了这一点,并没有对其进行测试。应该工作......

答案 1 :(得分:7)

this question中提供了一个更简单(我认为)的解决方案,关键是selectedItemPostion attribute of the Spinner的使用,它不在问题中包含的代码中,而是在回购中链接到: #

我成功地使用了上述方法。这确实需要从位置到实际的微调器列表项进行映射,但无论如何我需要为我的用例执行此操作。

答案 2 :(得分:3)

您可以使用Inverse Binding来实现此目的。您需要定义两个自定义绑定。

  1. 从微调器获取最新值并在模型中设置。
  2. 在微调器中选择新值时触发事件。
  3. 要从微调器中获取所选值,请将此方法添加到自定义绑定中。

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

    要在微调器中选择新值时触发事件

    @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);
        }
      }
    

    现在在你的布局文件中只需使用上面的绑定:

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

答案 3 :(得分:0)

为Spinner实现双向绑定

1)使用自定义属性并添加双向绑定表达式将数据模型的属性绑定到自定义属性,在下面的代码中,bind:paymentMode是自定义属性。

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

2)然后,为了提供在对该属性进行数据绑定(数据模型到微调器)时需要使用的行为或setter方法,需要定义BindingAdapter。当发生绑定时,我们需要设置默认选择值并将项目选择的侦听器添加到spinner,并且当项目选择事件发生时,我们需要通知数据绑定框架通过使用InverseBindingListener来启动反向绑定来捕获值。

@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)定义逆绑定适配器(spinner到数据模型),框架用它来捕获用户选择的值并将其设置为数据模型。当InverseBindingListener获得通知时会调用它。

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

有关数据绑定和spinner双向绑定实现的更多信息,请参阅 http://www.zoftino.com/android-data-binding-library-tutorial