Data Bindingを使ってみる その6
さて、またまた今回も公式に従ってData Bindingを見ていきます。
今回はBindingAdapterアノテーションを使って、ImageViewに画像を表示する属性とSetterを追加します。
今回は例として、画像のURLをセットすると画像をロードして表示する属性をImageViewに付与してみます。
BindingAdapterアノテーション
BindingAdapterアノテーションを利用して、Activity側からImageViewに画像のURLをセットして表示する属性を追加します。
まずはActivityにBindingAdapterアノテーションを定義したメソッドを用意します。
[MainActivity.java]
public class MainActivity extends AppCompatActivity { private Hanter hanter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final ActivityMainBinding binder = DataBindingUtil.setContentView(this, R.layout.activity_main); hanter = new Hanter("ハンタくん", "MAN"); binder.setHanter(hanter); binder.btnChangeGender.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { hanter.gender.set("WOMAN"); } }); } @BindingAdapter("loadImg") ・・・21行目 public static void setImage(ImageView view, String oldUrl, String newUrl) { if(!newUrl.equals(oldUrl)) { Picasso.with(view.getContext()).load(newUrl).into(view); } }
注目は21行目以降です。
BindingAdapterアノテーションに指定したloadImgが属性名となり、名前空間"app"で属性が使用できます。
レイアウトXMLにImageViewを追加し、loadImg属性を実装します。
[activity_main.xml]
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="activity" type="techium.hatenablog.com.monhaan1.MainActivity"/> <variable name="hanter" type="techium.hatenablog.com.monhaan1.Hanter"/> <variable name="imageUrl" type="String"/> ・・・7行目 </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"> <TextView android:id="@+id/txt_hello" android:text="hello, Hanter!" android:layout_alignParentTop="true" android:layout_alignParentLeft="true" android:layout_width="wrap_content" android:layout_height="wrap_content"/> (・・・略・・・) <ImageView android:id="@+id/img_sample" android:layout_width="40dp" android:layout_height="40dp" app:loadImg="@{imageUrl}" ・・・33行目 android:layout_below="@id/txt_gender"/> <Button android:id="@+id/btn_change_gender" android:text="change gender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/img_sample"/> </RelativeLayout> </layout>
8行目でURLをバインドするためのString型変数"imageUrl"を定義しています。
34行目にloadImg属性を実装し、8行目で定義したString型の変数をセットしています。
これで、自動生成されたsetImageUrlメソッドをActivity側から呼ぶことで、loadImg属性にURLをバインドする準備ができました。
では実際に画像のURLバインドしてみます。
[MainActivity.java]
public class MainActivity extends AppCompatActivity { private Hanter hanter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final ActivityMainBinding binder = DataBindingUtil.setContentView(this, R.layout.activity_main); hanter = new Hanter("ハンタくん", "MAN"); binder.setHanter(hanter); binder.setImageUrl("http://hogefuga.com/icon.png"); ・・・12行目 binder.btnChangeGender.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { hanter.gender.set("WOMAN"); } }); } @BindingAdapter("loadImg") public static void setImage(ImageView view, String url) { Picasso.with(view.getContext()).load(url).into(view); }
12行目でURLをバインドする処理を追加しました。
これでloadImgにURLがバインドされると同時にsetImageメソッドが呼び出され、Picassoで画像を取得する処理が実行されます。
["]
BindingAdapterアノテーションによるメソッドの定義はアプリ全体に影響を及ぼします。
BindingAdapterアノテーションを定義する専用のクラスを用意するなどすると良いかもしれません。
public class BindingUtils { @BindingAdapter({"loadImg"}) public static void setImage(ImageView view, String url) { Picasso.with(view.getContext()).load(url).into(view); } }
おまけ Picasso
今回、画像を取得するために使用したPicassoは、URLやリソースフォルダなどから画像を取得してImageViewにセットするまでをたった1行で記述することができる便利なOSSライブラリ(Apache License 2.0)です。
Picasso.with(view.getContext()).load(url).into(view);
以下のようにすれば、ネットワークの問題などで画像が取得できなかった場合に、リソースフォルダからアイコン(ここではR.drawable.gohan)を取得して表示させることもできます。
Picasso.with(view.getContext()).load(newUrl).error(R.drawable.gohan).into(view);
今日はここまでにします。