Data Bindingを使ってみる その3
前回、前々回に引き続き、今回もData Bindingです。
今回は、"Import"について見ていきます。
<data> <import type="android.view.View"/> </data>
Data Bindingを使用しているLayoutファイルの中では、クラスファイルをImportすることで、Layoutファイル内でJavaのようにImportしたクラスにアクセスすることができます。
例えば、以下のようなサンプルを見てみます。
[activity_main.xml]
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <import type="android.view.View"/> ・・・5行目 <import type="monhaan.example.com.monhaan.Const"/> <variable name="activity" type="monhaan.example.com.monhaan.MainActivity"/> <variable name="hanter" type="monhaan.example.com.monhaan.Hanter"/> </data> <RelativeLayout 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"> (・・・略・・・) <Spinner android:id="@+id/spn_weapon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/lbl_gender"></Spinner> <TextView android:id="@+id/lbl_selected_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{String.format(Const.msg, hanter.weapon)}" ・・・31行目 android:visibility="@{hanter.isHaveWeapon? View.VISIBLE : View.INVISIBLE}" android:layout_below="@id/spn_weapon"> </TextView> </RelativeLayout> </layout>
[Const.java]
public class Const { public static String msg = "%sを装備しました。"; }
前回との違いは、武器を選択するためのSpinnerをLayoutファイルに追加しつつ、「<武器>が選択されました。」とメッセージを表示するためのTextViewを追加しています。
(ボタンは邪魔なので消しましたがあまり関係はありません。)
ポイントは、
1.5行目でandroid標準のViewパッケージをImportし、31行目でImportしたViewパッケージを利用し、TextViewのVisibleを設定しています。
31行目ではさらに、javaの三項演算子を用いて、後述するHanterクラスのhaveWeaponプロパティの値によって、Visible設定を切り替えています。
(武器を持っている場合はメッセージを表示、持っていない場合は非表示とする)
2.また、6行目で今回自分で新たに定義したConstクラスをImportし、32行目でImportしたConstクラスに定義したメッセージにアクセスしています。
さらに、"%s"の部分をString#formatメソッドを用いて武器名で置き換えています。
String#formatメソッドを使うにはjava.lang.*のImportが必要かと思いきや、どうやら自動でImportされるようです。
Activityは以下のように修正しています。
public class MainActivity extends AppCompatActivity { public Hanter hanter; public List<String> WEAPONS = Arrays.asList("装備なし","大剣","ハンマー"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityMainBinding binder = DataBindingUtil.setContentView(this, R.layout.activity_main); (・・・略・・・) // 武器を選択するためのSpinnetを準備 ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item); adapter.addAll(WEAPONS); binder.spnWeapon.setAdapter(adapter); binder.spnWeapon.setOnItemSelectedListener(onItemSelectedListener); } public AdapterView.OnItemSelectedListener onItemSelectedListener = new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if(position >= 1){ // 武器を装備した hanter.setHaveWeapon(true); hanter.setWeapon(WEAPONS.get(position)); // 装備した武器の名前をHanterクラスのプロパティにセット }else{ // 武器を装備していない hanter.setHaveWeapon(false); } } @Override public void onNothingSelected(AdapterView<?> parent) { } }; }
Hanterクラスには、前回と比較すると武器(weapon)と武器の所持状態を示すフラグ(haveWeapon)をそれぞれプロパティとして追加しています。
public class Hanter extends BaseObservable{ private String name; private String gender; private boolean haveWeapon; private String weapon; public Hanter(String name, String gender){ this.name = name; this.gender = gender; this.haveWeapon = false; this.weapon = ""; } (・・・略・・・) @Bindable public String getWeapon() { return weapon; } public void setWeapon(String weapon) { this.weapon = weapon; notifyPropertyChanged(monhaan.example.com.monhaan.BR.weapon); } }
実行結果は以下のような感じです。
上記の例では便宜上Constクラスにメッセージを定義していますが、strings.xmlを用いる場合は、以下のようにすることもできます。
[activity_main.xml]
(・・・略・・・) <TextView android:id="@+id/lbl_selected_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{@string/msg_have_weapon(hanter.weapon)}" ・・・6行目 android:visibility="@{hanter.isHaveWeapon? View.VISIBLE : View.INVISIBLE}" android:layout_below="@id/spn_weapon"> </TextView> (・・・略・・・)
6行目でstrings.xmlからメッセージ文字列を取得しつつ、%sに武器をバインドしています。
[strings.xml]
<resources> <string name="app_name">MonHaan</string> <string name="msg_have_weapon">%sを装備しました。</string> </resources>
さて、今日はここまでにします。