2017/2/3 更新
コメントでご教授いただいたとおり、android:selectedItemPositionという定義済みattributeが既に存在していましたのでそちらを利用するよう改めました。
参考:Android data bindingで定義済みの属性リスト - Qiita
選択肢としてのテキストではなく選択位置に応じたコード値を取得したいとか、別の処理に応じてコード側からSpinnerの選択位置を操作したいというようなことってギョームアプリではよくあることだと思います。
今まではActivityなりFragmentなりにゴリゴリ処理を書いていましたが、DataBindingを導入してもうちょっと効率よくできないかと考えてみました。
コード
BindingAdapter
AdapterView.selectedItemPositionを利用しますので、TextViewのandroid:text attributeにStringをバインドできるようにするための記述を加えるだけです。
public class DataBindingAdapter {
@BindingAdapter("android:text")
public static void setTextViewText(TextView textView, String text) {
if (text != null) {
textView.setText(text);
} else {
textView.setText("");
}
}
}
ViewModel
今回はサンプルのためViewModelだけ定義しています。
public class MainViewModel extends BaseObservable {
private final String[] values;
private final View.OnClickListener onClickListener;
private String selectedText;
private int selectedPosition;
public MainViewModel(String[] values) {
this.values = values;
this.onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
setSelectedPosition(0);
}
};
}
public View.OnClickListener getOnClickListener() {
return onClickListener;
}
@Bindable
public String getSelectedText() {
return selectedText;
}
@Bindable
public int getSelectedPosition() {
return selectedPosition;
}
public void setSelectedText(String selectedText) {
this.selectedText = selectedText;
notifyPropertyChanged(BR.selectedText);
}
public void setSelectedPosition(int selectedPosition) {
this.selectedPosition = selectedPosition;
notifyPropertyChanged(BR.selectedPosition);
setSelectedText(this.values[selectedPosition]);
}
}
レイアウト
activity_main.xmlのレイアウトはこんな感じです。Spinnerの選択肢に応じたテキストをTextViewに表示するのと、Buttenを押したらSpinnerの選択位置を先頭にリセットするのが目標です。
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
<variable
name="viewModel"
type="com.example.trs.spinnerbindingsample.MainViewModel"/>
</data>
<RelativeLayout
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.trs.spinnerbindingsample.MainActivity">
<Spinner
android:id="@+id/spinner"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/spinner_code"
android:selectedItemPosition="@={viewModel.selectedPosition}"
/>
<TextView
android:id="@+id/text"
android:layout_below="@id/spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="@{viewModel.selectedText}"
/>
<Button
android:layout_below="@id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="リセット"
android:onClick="@{viewModel.onClickListener}"
/>
</RelativeLayout>
</layout>
MainActivity.javaはDataBindingを定義するだけです。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainViewModel viewModel = new MainViewModel(getResources().getStringArray(R.array.spinner_value));
binding.setViewModel(viewModel);
}
リソース
Spinnerで表示するためのstring-arrayとそれに応じたテキストを収めたstring-arrayを定義します。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="spinner_code">
<item>我が名はブリュンヒルデ!</item>
<item>闇に飲まれよ!</item>
<item>煩わしい太陽ね!</item>
<item>我が友よ!</item>
<item>我に力を!</item>
</string-array>
<string-array name="spinner_value">
<item>神崎蘭子です!</item>
<item>お疲れ様です!</item>
<item>おはようございます!</item>
<item>プロデューサーさん!</item>
<item>レッスンお願いします!</item>
</string-array>
</resources>
実行
参考
java - Android spinner Data Binding using XML and show the selected values - Stack Overflow