Android 微调器 Data Binding 使用 XML 并显示所选值

我正在使用新的Android数据绑定,它工作得很好。我能够使用EditText,TextView,Radio和notbox执行数据绑定。现在,我无法在微调器中进行数据绑定。

在下面的链接中找到了一些线索:Android微调器数据绑定与xml布局

但是,仍然无法找到解决方案。还需要执行双向数据绑定。应反映微调器数据所选值。

有人可以给我举个例子吗?

这是我的代码: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>

视图模型:

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

答案 1

1 线解决方案

android:selectedItemPosition="@={item.selectedItemPosition}"

就是这样!无需自定义绑定适配器。

微调器已经支持按属性和 的双向绑定。查看安卓文档selectionselectedItemPosition

您只需要使用双向绑定,以便微调器上的更改反映在模型字段上。selectedItemPosition

项目.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}"
    >

主要活动.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()]);
    }
}

如果您需要随时从代码中获取选定的项目,请使用此

binding.getItem().getSelectedItemPosition(); // get selected position
getResources().getStringArray(R.array.items)[binding.getItem().getSelectedItemPosition()]) // get selected item

如果需要以编程方式更改变量,请将其@Bindable

binding.getItem().setSelectedItemPosition(4);

否则,您可以删除@Bindable通知PropertyChanged(BR.selectedItemPosition);

您可以使用 BaseObservable ObservableFieldLive Data 中的任何一个。这取决于你。我使用BaseObservable是因为它非常简单,只需从BaseObservable扩展即可,现在所有字段都是可观察的。


答案 2

我发现一些东西可能会有所帮助,但它不在双向数据绑定的官方文档中。

1. 双向数据绑定的“@=”用法

2. 双向自定义数据绑定需要“绑定适配器”和“反向绑定适配器”注释来实现此目的。

对于第一项,许多博主展示了“@=”在双向数据绑定中的用法。https://halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-android/

对于第二项,正如@George Mound在这里回复的那样(当编辑文本的默认文本是浮点值时,编辑文本光标重置为左),EditText可以使用“BindingAdapter”和“InverseBindingAdapter”注释双向绑定。

按照说明,您可以为微调器构建双向绑定方法。

首先,创建您的视图模型或使用Pojo

视图模型

public class ViewModel {
    private ObservableField<String> text;
    public ViewModel() {
        text = new ObservableField<>();
    }
    public ObservableField<String> getText() {
        return text;
    }
}

波霍

public class ViewModel {
    private String text;
    public String getText() {
        return text;
    }

    public void setText(String text)
    {
       this.text = text;
    }
}

其次,将其添加到 xml 中。

  <android.support.v7.widget.AppCompatSpinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:entries="@array/days"
            bind:selectedValue="@={viewModel.text}"/>

第三,添加你的绑定工具

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

}

如您所见,它使用“selectedValue”作为默认所选值的变量,但什么是“selectedValueAttrChanged”?我认为这个很棘手(我不知道,为什么它在调用时不是空的),它不需要添加到xml中,因为它只是用于侦听微调器中更改的项目的回调。然后你设置onItemSelectedListener并将其设置为调用InverseBindingListener onchange()函数(文档和示例在这里:https://developer.android.com/reference/android/databinding/InverseBindingAdapter.html默认事件将是“android:textAttrChanged”,如果你想有自定义双向绑定反向绑定,你需要使用带有后缀“AttrChanged”的属性

事件的默认值是后缀为“AttrChanged”的属性名称。在上面的示例中,默认值应为 android:textAttrChanged,即使未提供也是如此。

最后,在你的活动和你的字符串中.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());
}

字符串.xml

<array name="days">
    <item name="Mon">Monday</item>
    <item name="Tue">Tuesday</item>
    <item name="Wed">Wednesday</item>
</array>

运行代码时,它将显示“星期三”作为微调器的默认值。


推荐