LoginSignup
17
17

More than 5 years have passed since last update.

DataBindingを使ってSpinnerの選択位置を得たり操作したりしたい

Last updated at Posted at 2017-01-19

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>

実行

初期状態

Spinner展開して選択

選択後

参考

java - Android spinner Data Binding using XML and show the selected values - Stack Overflow

Android BindingAdapter order of execution? - Stack Overflow

今更遅れてDataBinding事始め(3.7) - exception think

17
17
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17